package org.tmatesoft.svn.core.internal.wc17;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.tmatesoft.svn.core.SVNCommitInfo;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.internal.util.SVNHashSet;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.ISVNUpdateEditor;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNFileListUtil;
import org.tmatesoft.svn.core.internal.wc.SVNFileType;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc.SVNStatusEditor;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea;
import org.tmatesoft.svn.core.internal.wc.admin.SVNTranslator;
import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb;
import org.tmatesoft.svn.core.internal.wc17.db.Structure;
import org.tmatesoft.svn.core.internal.wc17.db.StructureFields;
import org.tmatesoft.svn.core.internal.wc2.ng.ISvnDiffCallback;
import org.tmatesoft.svn.core.internal.wc2.ng.SvnDiffCallbackResult;
import org.tmatesoft.svn.core.io.diff.SVNDeltaProcessor;
import org.tmatesoft.svn.core.io.diff.SVNDiffWindow;
import org.tmatesoft.svn.core.wc.ISVNOptions;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc2.SvnChecksum;
import org.tmatesoft.svn.util.SVNLogType;
public class SVNDiffEditor17 implements ISVNUpdateEditor {
private long targetRevision;
private boolean isRootOpen;
private File localTarget;
private SVNDepth depth;
private SVNDirectoryInfo currentDirectory;
private SVNWCContext wcContext;
private File workingCopyRoot;
private boolean isCompareToBase;
private boolean isReverseDiff;
private ISvnDiffCallback diffCallback;
private boolean useAncestry;
private SVNFileInfo currentFile;
private SVNDeltaProcessor deltaProcessor;
private File tempDirectory;
private Collection<String> changeLists;
private String relativeToDirectory;
private boolean diffUnversioned;
private boolean diffCopiedAsAdded;
public SVNDiffEditor17(SVNWCContext wcContext, File workingCopyRoot, File localTarget, SVNDepth depth,
boolean compareToBase, boolean reverseDiff, ISvnDiffCallback diffCallback, boolean useAncestry,
Collection<String> changeLists, boolean diffUnversioned, boolean diffCopiedAsAdded) {
this.wcContext = wcContext;
this.workingCopyRoot = workingCopyRoot;
this.localTarget = localTarget;
this.depth = depth;
isCompareToBase = compareToBase;
isReverseDiff = reverseDiff;
this.diffCallback = diffCallback;
this.useAncestry = useAncestry;
this.changeLists = changeLists;
this.diffUnversioned = diffUnversioned;
this.diffCopiedAsAdded = diffCopiedAsAdded;
this.deltaProcessor = new SVNDeltaProcessor();
}
public long getTargetRevision() {
return targetRevision;
}
public File getWorkingCopyRoot() {
return workingCopyRoot;
}
public ISvnDiffCallback getDiffCallback() {
return diffCallback;
}
private SvnDiffCallbackResult getDiffCallbackResult() {
return null;
}
private boolean isDiffCopiedAsAdded() {
return diffCopiedAsAdded;
}
private boolean isDiffUnversioned() {
return diffUnversioned;
}
private File createTempDirectory() throws SVNException {
return SVNFileUtil.createTempDirectory("diff");
}
public void targetRevision(long revision) throws SVNException {
this.targetRevision = revision;
}
public void openRoot(long revision) throws SVNException {
this.isRootOpen = true;
currentDirectory = createDirInfo(null, "", false, depth);
}
public void deleteEntry(String path, long revision) throws SVNException {
File fullPath = new File(getWorkingCopyRoot(), path);
final SVNWCContext.ScheduleInternalInfo schedule;
final Structure<StructureFields.NodeInfo> nodeInfo;
try {
schedule = wcContext.getNodeScheduleInternal(fullPath, true, false);
nodeInfo = wcContext.getDb().readInfo(fullPath, StructureFields.NodeInfo.kind);
} catch (SVNException e) {
//TODO (if doesn't exist call exit this method)
throw e;
}
String name = SVNPathUtil.tail(path);
currentDirectory.comparedEntries.add(name);
if (!isCompareToBase && schedule.schedule == SVNWCContext.SVNWCSchedule.delete) {
return;
}
final ISVNWCDb.SVNWCDbKind nodeKind = nodeInfo.get(StructureFields.NodeInfo.kind);
if (nodeKind == ISVNWCDb.SVNWCDbKind.File) {
if (isReverseDiff) {
final SVNProperties baseProps = wcContext.getDb().getBaseProps(fullPath);
getDiffCallback().fileDeleted(getDiffCallbackResult(), fullPath, null, null, null, null, baseProps);
} else {
reportAddedFile(currentDirectory, fullPath);
}
} else if (nodeKind == ISVNWCDb.SVNWCDbKind.Dir) {
SVNDirectoryInfo info = createDirInfo(currentDirectory, path, false, SVNDepth.INFINITY);
reportAddedDir(info);
}
}
private void reportAddedDir(SVNDirectoryInfo info) throws SVNException {
final File fullPath = new File(getWorkingCopyRoot(), info.path);
if (wcContext.matchesChangelist(new File(getWorkingCopyRoot(), info.path), changeLists)) {
SVNProperties wcProps;
if (isCompareToBase) {
wcProps = wcContext.getPristineProps(fullPath);
} else {
wcProps = wcContext.getActualProps(fullPath);
}
SVNProperties propDiff = computePropsDiff(new SVNProperties(), wcProps);
if (!propDiff.isEmpty()) {
getDiffCallback().dirPropsChanged(getDiffCallbackResult(), new File(getWorkingCopyRoot(), info.path), true, propDiff, null);
}
}
final List<File> children = wcContext.getNodeChildren(fullPath, false);
for (File child : children) {
final SVNWCContext.ScheduleInternalInfo schedule = wcContext.getNodeScheduleInternal(child, true, false);
if (!isCompareToBase && schedule.schedule == SVNWCContext.SVNWCSchedule.delete) {
continue;
}
final ISVNWCDb.WCDbBaseInfo baseInfo = wcContext.getDb().getBaseInfo(child, ISVNWCDb.WCDbBaseInfo.BaseInfoField.kind);
if (baseInfo.kind == ISVNWCDb.SVNWCDbKind.File) {
reportAddedFile(info, child);
} else if (baseInfo.kind == ISVNWCDb.SVNWCDbKind.Dir) {
if (info.depth.compareTo(SVNDepth.FILES) > 0 ||
info.depth == SVNDepth.UNKNOWN) {
SVNDepth depthBelowHere = info.depth;
if (depthBelowHere == SVNDepth.IMMEDIATES) {
depthBelowHere = SVNDepth.EMPTY;
}
SVNDirectoryInfo childInfo = createDirInfo(info,
SVNPathUtil.append(info.path, child.getName()),
false,
depthBelowHere);
reportAddedDir(childInfo);
}
}
}
}
private void reportAddedFile(SVNDirectoryInfo info, File entryPath) throws SVNException {
if (!wcContext.matchesChangelist(entryPath, changeLists)) {
return;
}
if (!matchesLocalTarget(entryPath)) {
return;
}
final SVNWCContext.ScheduleInternalInfo schedule = wcContext.getNodeScheduleInternal(entryPath, false, true);
final ISVNWCDb.WCDbInfo wcDbInfo = wcContext.getDb().readInfo(entryPath, ISVNWCDb.WCDbInfo.InfoField.revision);
if (schedule.copied) {
if (isCompareToBase) {
return;
}
reportModifiedFile(info, entryPath);
return;
}
final SVNProperties wcProps;
if (isCompareToBase) {
wcProps = wcContext.getPristineProps(entryPath);
} else {
wcProps = wcContext.getActualProps(entryPath);
}
String mimeType = wcProps.getStringValue(SVNProperty.MIME_TYPE);
SVNProperties propDiff = computePropsDiff(new SVNProperties(), wcProps);
File sourceFile;
if (isCompareToBase) {
final ISVNWCDb.WCDbBaseInfo baseInfo = wcContext.getDb().getBaseInfo(entryPath, ISVNWCDb.WCDbBaseInfo.BaseInfoField.checksum);
sourceFile = wcContext.getDb().getPristinePath(entryPath, baseInfo.checksum);
} else {
sourceFile = detranslateFile(entryPath);
}
getDiffCallback().fileAdded(getDiffCallbackResult(), entryPath, null, sourceFile, 0, wcDbInfo.revision, null, mimeType, null, -1, propDiff, null);
}
private void reportModifiedFile(SVNDirectoryInfo dirInfo, File entryPath) throws SVNException {
if (!wcContext.matchesChangelist(entryPath, changeLists)) {
return;
}
if (!matchesLocalTarget(entryPath)) {
return;
}
final SVNWCContext.ScheduleInternalInfo schedule = wcContext.getNodeScheduleInternal(entryPath, true, true);
SVNWCContext.SVNWCSchedule newSchedule = schedule.schedule;
if (!isDiffCopiedAsAdded() && schedule.copied) {
newSchedule = null;
}
if (!useAncestry && schedule.schedule == SVNWCContext.SVNWCSchedule.replace) {
newSchedule = null;
}
SVNProperties propDiff = null;
SVNProperties baseProps = null;
SvnChecksum checksum;
try {
final Structure<StructureFields.NodeInfo> infoStructure = wcContext.getDb().readInfo(entryPath, StructureFields.NodeInfo.checksum);
checksum = infoStructure.<SvnChecksum>get(StructureFields.NodeInfo.checksum);
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() == SVNErrorCode.ENTRY_NOT_FOUND) {
checksum = null;
} else {
throw e;
}
}
final File pristineFile = checksum == null ? null : wcContext.getDb().getPristinePath(entryPath, checksum);
SVNProperties pristineProps = wcContext.getPristineProps(entryPath);
if (pristineProps == null) {
pristineProps = new SVNProperties();
}
if (schedule.schedule != SVNWCContext.SVNWCSchedule.delete) {
if (isDiffCopiedAsAdded() && schedule.copied) {
baseProps = new SVNProperties();
propDiff = wcContext.getActualProps(entryPath);
} else {
baseProps = pristineProps;
boolean modified = wcContext.isPropsModified(entryPath);
if (modified) {
propDiff = computePropsDiff(baseProps, wcContext.getActualProps(entryPath));
} else {
propDiff = new SVNProperties();
}
}
} else {
baseProps = pristineProps;
}
boolean isAdded = newSchedule != null && schedule.schedule == SVNWCContext.SVNWCSchedule.add;
if ((schedule.schedule == SVNWCContext.SVNWCSchedule.delete || schedule.schedule == SVNWCContext.SVNWCSchedule.replace)) {
String mimeType = pristineProps.getStringValue(SVNProperty.MIME_TYPE);
getDiffCallback().fileDeleted(getDiffCallbackResult(), entryPath, pristineFile, null, mimeType, null,
pristineProps);
isAdded = schedule.schedule == SVNWCContext.SVNWCSchedule.replace;
}
if (isAdded) {
final ISVNWCDb.WCDbInfo wcDbInfo = wcContext.getDb().readInfo(entryPath, ISVNWCDb.WCDbInfo.InfoField.revision);
String mimeType = wcContext.getActualProps(entryPath).getStringValue(SVNProperty.MIME_TYPE);
File tmpFile = detranslateFile(entryPath);
SVNProperties originalProperties = null;
long revision = wcDbInfo.revision;
if (schedule.copied && isDiffCopiedAsAdded()) {
originalProperties = new SVNProperties();
revision = 0;
} else {
originalProperties = pristineProps;
}
getDiffCallback().fileAdded(getDiffCallbackResult(), entryPath, null, tmpFile, -1, revision, mimeType, null, null, -1, propDiff, originalProperties);
} else if (newSchedule == null || schedule.schedule == SVNWCContext.SVNWCSchedule.normal) {
boolean modified = wcContext.isTextModified(entryPath, false);
File tmpFile = null;
if (modified) {
tmpFile = detranslateFile(entryPath);
}
if (modified || (propDiff != null && !propDiff.isEmpty())) {
String baseMimeType = pristineProps.getStringValue(SVNProperty.MIME_TYPE);
String mimeType = wcContext.getActualProps(entryPath).getStringValue(SVNProperty.MIME_TYPE);
final ISVNWCDb.WCDbInfo wcDbInfo = wcContext.getDb().readInfo(entryPath, ISVNWCDb.WCDbInfo.InfoField.revision);
getDiffCallback().fileChanged(getDiffCallbackResult(), entryPath, modified ? pristineFile : null, tmpFile, wcDbInfo.revision, -1,
baseMimeType, mimeType, propDiff, baseProps);
}
}
}
public void addDir(String path, String copyFromPath, long copyFromRevision) throws SVNException {
SVNDepth subDirDepth = currentDirectory.depth;
if (subDirDepth == SVNDepth.IMMEDIATES) {
subDirDepth = SVNDepth.EMPTY;
}
currentDirectory = createDirInfo(currentDirectory, path, true, subDirDepth);
}
public void openDir(String path, long revision) throws SVNException {
SVNDepth subDirDepth = currentDirectory.depth;
if (subDirDepth == SVNDepth.IMMEDIATES) {
subDirDepth = SVNDepth.EMPTY;
}
currentDirectory = createDirInfo(currentDirectory, path, false, subDirDepth);
}
public void changeDirProperty(String name, SVNPropertyValue value) throws SVNException {
if (currentDirectory.propertyDiff == null) {
currentDirectory.propertyDiff = new SVNProperties();
}
currentDirectory.propertyDiff.put(name, value);
}
public void closeDir() throws SVNException {
final File fullPath = new File(getWorkingCopyRoot(), currentDirectory.path);
// display dir prop changes.
SVNProperties diff = currentDirectory.propertyDiff;
if (diff != null && !diff.isEmpty()) {
// reverse changes
SVNProperties originalProps = null;
if (currentDirectory.isAdded) {
originalProps = new SVNProperties();
} else {
if (isCompareToBase) {
originalProps = wcContext.getPristineProps(fullPath);
} else {
originalProps = wcContext.getActualProps(fullPath);
SVNProperties baseProps = wcContext.getPristineProps(fullPath);
SVNProperties reposProps = applyPropChanges(baseProps, currentDirectory.propertyDiff);
diff = computePropsDiff(originalProps, reposProps);
}
}
if (!isReverseDiff) {
reversePropChanges(originalProps, diff);
}
getDiffCallback().dirPropsChanged(getDiffCallbackResult(), new File(getWorkingCopyRoot(), currentDirectory.path), currentDirectory.isAdded, diff, originalProps);
currentDirectory.comparedEntries.add("");
}
if (!currentDirectory.isAdded) {
localDirectoryDiff(currentDirectory);
}
String name = SVNPathUtil.tail(currentDirectory.path);
currentDirectory = currentDirectory.parent;
if (currentDirectory != null) {
currentDirectory.comparedEntries.add(name);
}
}
public void addFile(String path, String copyFromPath, long copyFromRevision) throws SVNException {
String name = SVNPathUtil.tail(path);
currentFile = createFileInfo(currentDirectory, path, true);
currentDirectory.comparedEntries.add(name);
}
public void openFile(String path, long revision) throws SVNException {
String name = SVNPathUtil.tail(path);
currentFile = createFileInfo(currentDirectory, path, false);
currentDirectory.comparedEntries.add(name);
}
public void changeFileProperty(String path,String name, SVNPropertyValue value) throws SVNException {
if (currentFile.propertyDiff == null) {
currentFile.propertyDiff = new SVNProperties();
}
currentFile.propertyDiff.put(name, value);
}
public void applyTextDelta(String path, String baseChecksum) throws SVNException {
final File fullPath = new File(getWorkingCopyRoot(), path);
SVNWCContext.ScheduleInternalInfo schedule;
try {
schedule = wcContext.getNodeScheduleInternal(fullPath, false, true);
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) {
schedule = null;
} else {
throw e;
}
}
if (schedule != null && schedule.copied) {
currentFile.isAdded = false;
}
if (!currentFile.isAdded) {
SVNWCContext.PristineContentsInfo pristineContents = wcContext.getPristineContents(fullPath, false, true);
currentFile.pristineFile = pristineContents.path;
}
currentFile.file = createTempFile();
deltaProcessor.applyTextDelta(currentFile.pristineFile, currentFile.file, false);
}
public OutputStream textDeltaChunk(String path, SVNDiffWindow diffWindow) throws SVNException {
return deltaProcessor.textDeltaChunk(diffWindow);
}
public void textDeltaEnd(String path) throws SVNException {
deltaProcessor.textDeltaEnd();
}
public void closeFile(String commitPath, String textChecksum) throws SVNException {
final File fullPath = new File(workingCopyRoot, commitPath);
SVNProperties baseProperties = null;
if (!currentFile.isAdded) {
try {
baseProperties = wcContext.getDb().getBaseProps(fullPath);
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_PATH_NOT_FOUND) {
throw e;
}
}
}
if (baseProperties == null) {
baseProperties = new SVNProperties();
}
SVNProperties reposProperties = applyPropChanges(baseProperties, currentFile.propertyDiff);
String reposMimeType = reposProperties.getStringValue(SVNProperty.MIME_TYPE);
File reposFile = currentFile.file;
File localFile = null;
if (reposFile == null) {
final ISVNWCDb.WCDbBaseInfo baseInfo = wcContext.getDb().getBaseInfo(fullPath, ISVNWCDb.WCDbBaseInfo.BaseInfoField.checksum);
reposFile = wcContext.getDb().getPristinePath(fullPath, baseInfo.checksum);
}
SVNWCContext.ScheduleInternalInfo schedule;
try {
schedule = wcContext.getNodeScheduleInternal(fullPath, true, false);
} catch (SVNException e) {
if (e.getErrorMessage().getErrorCode() == SVNErrorCode.ENTRY_NOT_FOUND || e.getErrorMessage().getErrorCode() == SVNErrorCode.WC_PATH_NOT_FOUND) {
schedule = null;
} else {
throw e;
}
}
if (currentFile.isAdded || (!isCompareToBase && schedule != null && schedule.schedule == SVNWCContext.SVNWCSchedule.delete)) {
if (isReverseDiff) {
getDiffCallback().fileAdded(getDiffCallbackResult(), new File(getWorkingCopyRoot(), commitPath), null, reposFile, 0, targetRevision, reposMimeType, null, null, -1,
currentFile.propertyDiff, null);
} else {
getDiffCallback().fileDeleted(getDiffCallbackResult(), new File(getWorkingCopyRoot(), commitPath), reposFile, null, reposMimeType, null, reposProperties);
}
return;
}
boolean modified = currentFile.file != null;
if (!modified && !isCompareToBase) {
modified = wcContext.isTextModified(fullPath, false);
}
if (modified) {
if (isCompareToBase) {
final ISVNWCDb.WCDbBaseInfo baseInfo = wcContext.getDb().getBaseInfo(fullPath, ISVNWCDb.WCDbBaseInfo.BaseInfoField.checksum);
localFile = wcContext.getDb().getPristinePath(fullPath, baseInfo.checksum);
} else {
localFile = detranslateFile(fullPath);
}
} else {
localFile = null;
reposFile = null;
}
SVNProperties originalProps = null;
if (isCompareToBase) {
originalProps = baseProperties;
} else {
originalProps = wcContext.getDb().readPristineProperties(fullPath);
currentFile.propertyDiff = computePropsDiff(originalProps, reposProperties);
}
if (localFile != null || (currentFile.propertyDiff != null && !currentFile.propertyDiff.isEmpty())) {
String originalMimeType = originalProps.getStringValue(SVNProperty.MIME_TYPE);
if (currentFile.propertyDiff != null && !currentFile.propertyDiff.isEmpty() && !isReverseDiff) {
reversePropChanges(originalProps, currentFile.propertyDiff);
}
if (localFile != null || reposFile != null || (currentFile.propertyDiff != null && !currentFile.propertyDiff.isEmpty())) {
getDiffCallback().fileChanged(getDiffCallbackResult(), new File(getWorkingCopyRoot(), commitPath),
isReverseDiff ? localFile : reposFile,
isReverseDiff ? reposFile : localFile,
isReverseDiff ? -1 : targetRevision,
isReverseDiff ? targetRevision : -1,
isReverseDiff ? originalMimeType : reposMimeType,
isReverseDiff ? reposMimeType : originalMimeType,
currentFile.propertyDiff, originalProps);
}
}
}
public SVNCommitInfo closeEdit() throws SVNException {
if (!isRootOpen) {
localDirectoryDiff(createDirInfo(null, "", false, depth));
}
return null;
}
public void abortEdit() throws SVNException {
}
public void absentDir(String path) throws SVNException {
}
public void absentFile(String path) throws SVNException {
}
public void cleanup() {
if (tempDirectory != null) {
SVNFileUtil.deleteAll(tempDirectory, true);
}
}
private SVNProperties applyPropChanges(SVNProperties props, SVNProperties propChanges) {
SVNProperties result = new SVNProperties(props);
if (propChanges != null) {
for(Iterator names = propChanges.nameSet().iterator(); names.hasNext();) {
String name = (String) names.next();
SVNPropertyValue value = propChanges.getSVNPropertyValue(name);
if (value == null) {
result.remove(name);
} else {
result.put(name, value);
}
}
}
return result;
}
private void localDirectoryDiff(SVNDirectoryInfo info) throws SVNException {
if (isCompareToBase) {
return;
}
final File fullPath = new File(getWorkingCopyRoot(), info.path);
if (wcContext.matchesChangelist(new File(getWorkingCopyRoot(), info.path), changeLists) && !info.comparedEntries.contains("")) {
// generate prop diff for dir.
if (wcContext.isPropsModified(fullPath) && matchesLocalTarget(fullPath)) {
final SVNProperties baseProps = wcContext.getPristineProps(fullPath);
SVNProperties propDiff = baseProps.compareTo(wcContext.getActualProps(fullPath));
getDiffCallback().dirPropsChanged(getDiffCallbackResult(), new File(getWorkingCopyRoot(), info.path), info.isAdded, propDiff, baseProps);
}
}
if (info.depth == SVNDepth.EMPTY) {
return;
}
Set processedFiles = null;
if (isDiffUnversioned()) {
processedFiles = new SVNHashSet();
}
final List<File> children = wcContext.getNodeChildren(fullPath, false);
for (File child : children) {
if (processedFiles != null) {
processedFiles.add(child.getName());
}
if (info.comparedEntries.contains(child.getName())) {
continue;
}
info.comparedEntries.add(child.getName());
final Structure<StructureFields.NodeInfo> nodeInfoStructure = wcContext.getDb().readInfo(child, StructureFields.NodeInfo.kind);
final ISVNWCDb.SVNWCDbKind kind = nodeInfoStructure.get(StructureFields.NodeInfo.kind);
if (kind == ISVNWCDb.SVNWCDbKind.File) {
reportModifiedFile(info, child);
} else if (kind == ISVNWCDb.SVNWCDbKind.Dir) {
if (info.depth.compareTo(SVNDepth.FILES) > 0 ||
info.depth == SVNDepth.UNKNOWN) {
SVNDepth depthBelowHere = info.depth;
if (depthBelowHere == SVNDepth.IMMEDIATES) {
depthBelowHere = SVNDepth.EMPTY;
}
SVNDirectoryInfo childInfo = createDirInfo(info,
SVNPathUtil.append(info.path, child.getName()),
false,
depthBelowHere);
localDirectoryDiff(childInfo);
}
}
}
if (isDiffUnversioned()) {
throw new UnsupportedOperationException();//TODO
// String relativePath = dir.getRelativePath(myAdminInfo.getAnchor());
// diffUnversioned(dir.getRoot(), dir, relativePath, anchor, processedFiles);
}
}
private boolean matchesLocalTarget(File fullPath) {
return (localTarget == null || SVNPathUtil.isWithinBasePath(localTarget.getAbsolutePath(), fullPath.getAbsolutePath()));
}
private void diffUnversioned(File root, SVNAdminArea dir, String parentRelativePath, boolean anchor, Set processedFiles) throws SVNException {
File[] allFiles = SVNFileListUtil.listFiles(root);
for (int i = 0; allFiles != null && i < allFiles.length; i++) {
File file = allFiles[i];
if (SVNFileUtil.getAdminDirectoryName().equals(file.getName())) {
continue;
}
if (processedFiles != null && processedFiles.contains(file.getName())) {
continue;
}
if (dir != null) {
Collection globalIgnores = SVNStatusEditor.getGlobalIgnores(wcContext.getOptions());
Collection ignores = SVNStatusEditor.getIgnorePatterns(dir, globalIgnores);
String rootRelativePath = null;
boolean needToComputeRelativePath = false;
for (Iterator patterns = ignores.iterator(); patterns.hasNext();) {
String pattern = (String) patterns.next();
if (pattern.startsWith("/")) {
needToComputeRelativePath = true;
break;
}
}
if (needToComputeRelativePath) {
if (relativeToDirectory == null) {
File wcRoot = SVNWCUtil.getWorkingCopyRoot(dir.getRoot(), true);
relativeToDirectory = wcRoot.getAbsolutePath().replace(File.separatorChar, '/');
}
if (relativeToDirectory != null) {
rootRelativePath = file.getAbsolutePath().replace(File.separatorChar, '/');
rootRelativePath = SVNPathUtil.getPathAsChild(relativeToDirectory, rootRelativePath);
if (rootRelativePath != null && !rootRelativePath.startsWith("/")) {
rootRelativePath = "/" + rootRelativePath;
}
}
}
if (SVNStatusEditor.isIgnored(ignores, file, rootRelativePath)) {
continue;
}
}
// generate patch as for added file.
SVNFileType fileType = SVNFileType.getType(file);
if (fileType == SVNFileType.DIRECTORY) {
diffUnversioned(file, null, SVNPathUtil.append(parentRelativePath, file.getName()), false, null);
} else if (fileType == SVNFileType.FILE || fileType == SVNFileType.SYMLINK) {
String mimeType1 = null;
String mimeType2 = SVNFileUtil.detectMimeType(file, null);
String filePath = SVNPathUtil.append(parentRelativePath, file.getName());
getDiffCallback().fileAdded(getDiffCallbackResult(), new File(getWorkingCopyRoot(), filePath), null, file, -1, -1, mimeType1, mimeType2, null, -1, null, null);
}
}
}
private SVNDirectoryInfo createDirInfo(SVNDirectoryInfo parent, String path, boolean added,
SVNDepth depth) {
SVNDirectoryInfo info = new SVNDirectoryInfo();
info.parent = parent;
info.path = path;
info.isAdded = added;
info.depth = depth;
return info;
}
private SVNFileInfo createFileInfo(SVNDirectoryInfo parent, String path, boolean added) {
SVNFileInfo info = new SVNFileInfo();
info.path = path;
info.isAdded = added;
if (parent.isAdded) {
while(parent.isAdded) {
parent = parent.parent;
}
info.path = SVNPathUtil.append(parent.path, "fake");
}
return info;
}
private File detranslateFile(File fullPath) throws SVNException {
SVNProperties properties = wcContext.getPristineProps(fullPath);
if (properties == null) {
properties = new SVNProperties();
}
// SVNVersionedProperties properties = dir.getProperties(name);
String keywords = properties.getStringValue(SVNProperty.KEYWORDS);
String eolStyle = properties.getStringValue(SVNProperty.EOL_STYLE);
String charsetProp = properties.getStringValue(SVNProperty.CHARSET);
String mimeType = properties.getStringValue(SVNProperty.MIME_TYPE);
ISVNOptions options = wcContext.getOptions();
String charset = SVNTranslator.getCharset(charsetProp, mimeType, fullPath.getPath(), options);
boolean special = properties.getSVNPropertyValue(SVNProperty.SPECIAL) != null;
if (charset == null && keywords == null && eolStyle == null && (!special || !SVNFileUtil.symlinksSupported())) {
return fullPath;
}
byte[] eol = SVNTranslator.getEOL(eolStyle, options);
File tmpFile = createTempFile();
Map keywordsMap = SVNTranslator.computeKeywords(keywords, null, null, null, null, null, null);
SVNTranslator.translate(fullPath, tmpFile, charset, eol, keywordsMap, special, false);
return tmpFile;
}
private File createTempFile() throws SVNException {
File tmpFile = null;
try {
return File.createTempFile("diff.", ".tmp", getTempDirectory());
} catch (IOException e) {
SVNFileUtil.deleteFile(tmpFile);
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e.getMessage());
SVNErrorManager.error(err, SVNLogType.DEFAULT);
}
return null;
}
private File getTempDirectory() throws SVNException {
if (tempDirectory == null) {
tempDirectory = createTempDirectory();
}
return tempDirectory;
}
private static class SVNDirectoryInfo {
private boolean isAdded;
private String path;
private SVNProperties propertyDiff;
private SVNDirectoryInfo parent;
private Set comparedEntries = new SVNHashSet();
private SVNDepth depth;
}
private static class SVNFileInfo {
private boolean isAdded;
private String path;
private File file;
private File pristineFile;
private SVNProperties propertyDiff;
}
private static void reversePropChanges(SVNProperties base, SVNProperties diff) {
Collection namesList = new ArrayList(diff.nameSet());
for (Iterator names = namesList.iterator(); names.hasNext();) {
String name = (String) names.next();
SVNPropertyValue newValue = diff.getSVNPropertyValue(name);
SVNPropertyValue oldValue = base.getSVNPropertyValue(name);
if (oldValue == null && newValue != null) {
base.put(name, newValue);
diff.put(name, (SVNPropertyValue) null);
} else if (oldValue != null && newValue == null) {
base.put(name, (SVNPropertyValue) null);
diff.put(name, oldValue);
} else if (oldValue != null && newValue != null) {
base.put(name, newValue);
diff.put(name, oldValue);
}
}
}
private static SVNProperties computePropsDiff(SVNProperties props1, SVNProperties props2) {
SVNProperties propsDiff = new SVNProperties();
for (Iterator names = props2.nameSet().iterator(); names.hasNext();) {
String newPropName = (String) names.next();
if (props1.containsName(newPropName)) {
// changed.
SVNPropertyValue oldValue = props2.getSVNPropertyValue(newPropName);
SVNPropertyValue value = props1.getSVNPropertyValue(newPropName);
if (oldValue != null && !oldValue.equals(value)) {
propsDiff.put(newPropName, oldValue);
} else if (oldValue == null && value != null) {
propsDiff.put(newPropName, oldValue);
}
} else {
// added.
propsDiff.put(newPropName, props2.getSVNPropertyValue(newPropName));
}
}
for (Iterator names = props1.nameSet().iterator(); names.hasNext();) {
String oldPropName = (String) names.next();
if (!props2.containsName(oldPropName)) {
// deleted
propsDiff.put(oldPropName, (String) null);
}
}
return propsDiff;
}
}