package org.tmatesoft.svn.core.internal.wc2.ng; import java.io.File; import java.util.Collection; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; 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.wc17.SVNWCContext; 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.wc.SVNStatusType; import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver; import org.tmatesoft.svn.core.wc2.SvnChecksum; import org.tmatesoft.svn.core.wc2.SvnStatus; import org.tmatesoft.svn.core.wc2.SvnTarget; public class SvnDiffStatusReceiver implements ISvnObjectReceiver<SvnStatus> { private final SVNWCContext context; private final File anchor; private final ISVNWCDb db; private final ISvnDiffCallback callback; private final boolean showCopiesAsAdds; private final boolean gitFormat; private final boolean ignoreAncestry; private final Collection<String> changelists; public SvnDiffStatusReceiver(SVNWCContext context, File anchor, ISVNWCDb db, ISvnDiffCallback callback, boolean ignoreAncestry, boolean showCopiesAsAdds, boolean gitFormat, Collection<String> changelists) { this.context = context; this.anchor = anchor; this.db = db; this.callback = callback; this.ignoreAncestry = ignoreAncestry; this.showCopiesAsAdds = showCopiesAsAdds; this.gitFormat = gitFormat; this.changelists = changelists; } public SVNWCContext getContext() { return context; } public File getAnchor() { return anchor; } public ISVNWCDb getDb() { return db; } public ISvnDiffCallback getCallback() { return callback; } public boolean isIgnoreAncestry() { return ignoreAncestry; } public boolean isShowCopiesAsAdds() { return showCopiesAsAdds; } public boolean isGitFormat() { return gitFormat; } public void receive(SvnTarget target, SvnStatus status) throws SVNException { final SVNStatusType nodeStatus = status.getNodeStatus(); if (nodeStatus == SVNStatusType.STATUS_UNVERSIONED) { return; } else if (nodeStatus == SVNStatusType.OBSTRUCTED || nodeStatus == SVNStatusType.MISSING) { return; } final File localAbspath = target.getFile(); if (changelists != null && !context.matchesChangelist(localAbspath, changelists)) { return; } if (status.getKind() == SVNNodeKind.FILE) { if (status.getTextStatus() == SVNStatusType.STATUS_MODIFIED || status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED || status.getNodeStatus() == SVNStatusType.STATUS_DELETED || status.getNodeStatus() == SVNStatusType.STATUS_REPLACED || (isShowCopiesAsAdds() || isGitFormat()) && status.isCopied()) { final String path = SVNPathUtil.getRelativePath(getAnchor().getAbsolutePath(), localAbspath.getAbsolutePath()); fileDiff(localAbspath, path); } } else { //status.getKind() != SVNNodeKind.FILE if (status.getNodeStatus() == SVNStatusType.STATUS_DELETED || status.getNodeStatus() == SVNStatusType.STATUS_REPLACED || status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { String path = SVNPathUtil.getRelativePath(getAnchor().getAbsolutePath(), localAbspath.getAbsolutePath()); SVNProperties baseProps = getDb().readPristineProperties(localAbspath); if (baseProps == null) { baseProps = new SVNProperties(); } SVNProperties actualProps = getDb().readProperties(localAbspath); SVNProperties propChanges = SvnDiffEditor.computePropDiff(baseProps, actualProps); getCallback().dirPropsChanged(null, localAbspath, false, propChanges, baseProps); } } } private void fileDiff(File localAbspath, String path) throws SVNException { final Structure<StructureFields.NodeInfo> nodeInfo = getDb().readInfo(localAbspath, StructureFields.NodeInfo.status, StructureFields.NodeInfo.kind, StructureFields.NodeInfo.revision, StructureFields.NodeInfo.checksum, StructureFields.NodeInfo.originalReposRelpath, StructureFields.NodeInfo.opRoot, StructureFields.NodeInfo.hadProps, StructureFields.NodeInfo.propsMod, StructureFields.NodeInfo.haveBase, StructureFields.NodeInfo.haveMoreWork); ISVNWCDb.SVNWCDbStatus status = nodeInfo.get(StructureFields.NodeInfo.status); ISVNWCDb.SVNWCDbKind kind = nodeInfo.get(StructureFields.NodeInfo.kind); long revision = nodeInfo.lng(StructureFields.NodeInfo.revision); SvnChecksum checksum = nodeInfo.get(StructureFields.NodeInfo.checksum); File originalReposRelpath = nodeInfo.get(StructureFields.NodeInfo.originalReposRelpath); Object opRoot = nodeInfo.is(StructureFields.NodeInfo.opRoot); boolean hadProps = nodeInfo.is(StructureFields.NodeInfo.hadProps); boolean propsMod = nodeInfo.is(StructureFields.NodeInfo.propsMod); boolean haveBase = nodeInfo.is(StructureFields.NodeInfo.haveBase); boolean haveMoreWork = nodeInfo.is(StructureFields.NodeInfo.haveMoreWork); boolean replaced = false; boolean baseReplace = false; SvnChecksum baseChecksum = null; ISVNWCDb.SVNWCDbKind baseKind; ISVNWCDb.SVNWCDbStatus baseStatus; long baseRevision; File emptyFile; File pristineAbspath; if ((status == ISVNWCDb.SVNWCDbStatus.Added) && (haveBase || haveMoreWork)) { final ISVNWCDb.SVNWCDbNodeCheckReplaceData checkReplaceData = getDb().nodeCheckReplace(localAbspath); replaced = checkReplaceData.replace; baseReplace = checkReplaceData.baseReplace; if (replaced && baseReplace) { ISVNWCDb.WCDbBaseInfo baseInfo = getDb().getBaseInfo(localAbspath, ISVNWCDb.WCDbBaseInfo.BaseInfoField.status, ISVNWCDb.WCDbBaseInfo.BaseInfoField.kind, ISVNWCDb.WCDbBaseInfo.BaseInfoField.revision, ISVNWCDb.WCDbBaseInfo.BaseInfoField.checksum); baseStatus = baseInfo.status; baseKind = baseInfo.kind; baseRevision = baseInfo.revision; baseChecksum = baseInfo.checksum; if (baseStatus != ISVNWCDb.SVNWCDbStatus.Normal || (baseKind != kind)) { replaced = false; baseReplace = false; } } else { replaced = false; baseReplace = false; } } if (status == ISVNWCDb.SVNWCDbStatus.Added) { ISVNWCDb.WCDbAdditionInfo wcDbAdditionInfo = getDb().scanAddition(localAbspath, ISVNWCDb.WCDbAdditionInfo.AdditionInfoField.status); status = wcDbAdditionInfo.status; } //here we can create an empty file //but also we can create it on demand, that it better solution if (status == ISVNWCDb.SVNWCDbStatus.Deleted || (baseReplace && !isIgnoreAncestry())) { SvnChecksum delChecksum; SVNProperties delProps; File delTextAbspath; String delMimeType; if (baseReplace && !isIgnoreAncestry()) { delProps = getDb().getBaseProps(localAbspath); delChecksum = baseChecksum; } else { assert status == ISVNWCDb.SVNWCDbStatus.Deleted; delProps = getContext().getPristineProps(localAbspath); delChecksum = getDb().readPristineInfo(localAbspath).get(StructureFields.PristineInfo.checksum); } assert delChecksum != null; delTextAbspath = getDb().getPristinePath(localAbspath, delChecksum); if (delProps == null) { delProps = new SVNProperties(); } delMimeType = delProps.getStringValue(SVNProperty.MIME_TYPE); getCallback().fileDeleted(null, localAbspath, delTextAbspath, getEmptyFile(), delMimeType, null, delProps); if (status == ISVNWCDb.SVNWCDbStatus.Deleted) { return; } } if (checksum != null) { pristineAbspath = getDb().getPristinePath(localAbspath, checksum); } else if (baseReplace && isIgnoreAncestry()) { pristineAbspath = getDb().getPristinePath(localAbspath, baseChecksum); } else { pristineAbspath = getEmptyFile(); } if ((! baseReplace && status == ISVNWCDb.SVNWCDbStatus.Added) || (baseReplace && !isIgnoreAncestry()) || ((status == ISVNWCDb.SVNWCDbStatus.Copied || status == ISVNWCDb.SVNWCDbStatus.MovedHere) && (isShowCopiesAsAdds() || isGitFormat()))) { File translatedFile; SVNProperties pristineProps = new SVNProperties(); SVNProperties actualProps; String actualMimeType; SVNProperties propChanges; actualProps = getContext().getActualProps(localAbspath); if (actualProps == null) { actualProps = new SVNProperties(); } actualMimeType = actualProps.getStringValue(SVNProperty.MIME_TYPE); propChanges = SvnDiffEditor.computePropDiff(pristineProps, actualProps); translatedFile = getContext().getTranslatedFile(localAbspath, localAbspath, true, false, false, false, false); getCallback().fileAdded(null, localAbspath, (!isShowCopiesAsAdds() && isGitFormat() && status != ISVNWCDb.SVNWCDbStatus.Added) ? pristineAbspath : getEmptyFile(), translatedFile, 0, revision, null, actualMimeType, originalReposRelpath, -1, propChanges, pristineProps); } else { File translatedFile = null; SVNProperties pristineProps; boolean modified = getContext().isTextModified(localAbspath, false); if (modified) { translatedFile = getContext().getTranslatedFile(localAbspath, localAbspath, true, false, false, false, false); } if (baseReplace && isIgnoreAncestry()) { pristineProps = getDb().getBaseProps(localAbspath); } else { assert !replaced || status == ISVNWCDb.SVNWCDbStatus.Copied || status == ISVNWCDb.SVNWCDbStatus.MovedHere; pristineProps = getDb().readPristineProperties(localAbspath); if (pristineProps == null) { pristineProps = new SVNProperties(); } } String pristineMimeType = pristineProps.getStringValue(SVNProperty.MIME_TYPE); SVNProperties actualProps = getDb().readProperties(localAbspath); String actualMimeType = actualProps.getStringValue(SVNProperty.MIME_TYPE); SVNProperties propChanges = SvnDiffEditor.computePropDiff(pristineProps, actualProps); if (modified || !propChanges.isEmpty()) { getCallback().fileChanged(null, localAbspath, modified ? pristineAbspath : null, translatedFile, revision, -1, pristineMimeType, actualMimeType, propChanges, pristineProps); } } } private File getEmptyFile() throws SVNException { return null; } }