package org.tmatesoft.svn.core.internal.wc17.db; import org.tmatesoft.sqljet.core.SqlJetException; import org.tmatesoft.sqljet.core.schema.SqlJetConflictAction; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.db.SVNSqlJetDb; import org.tmatesoft.svn.core.internal.db.SVNSqlJetDeleteStatement; import org.tmatesoft.svn.core.internal.db.SVNSqlJetInsertStatement; import org.tmatesoft.svn.core.internal.db.SVNSqlJetSelectStatement; import org.tmatesoft.svn.core.internal.util.SVNDate; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.internal.util.SVNSkel; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext.CheckWCRootInfo; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.SVNWCDbKind; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.SVNWCDbStatus; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.WCDbBaseInfo; import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb.WCDbBaseInfo.BaseInfoField; import org.tmatesoft.svn.core.internal.wc17.db.SVNWCDb.DirParsedInfo; import org.tmatesoft.svn.core.internal.wc17.db.SVNWCDb.InsertBase; import org.tmatesoft.svn.core.internal.wc17.db.StructureFields.ExternalNodeInfo; import org.tmatesoft.svn.core.internal.wc17.db.statement.SVNWCDbSchema; import org.tmatesoft.svn.core.internal.wc17.db.statement.SVNWCDbSchema.EXTERNALS__Fields; import org.tmatesoft.svn.core.wc2.SvnChecksum; import org.tmatesoft.svn.util.SVNLogType; import java.io.File; import java.util.HashMap; import java.util.Map; import static org.tmatesoft.svn.core.internal.wc17.db.SvnWcDbStatementUtil.*; public class SvnWcDbExternals extends SvnWcDbShared { public static void addExternalDir(SVNWCDb db, File localAbspath, File wriPath, SVNURL reposRootUrl, String reposUuid, File recordAncestorAbspath, File recordedReposRelPath, long recordedPegRevision, long recordedRevision, SVNSkel workItems) throws SVNException { if (wriPath == null) { wriPath = SVNFileUtil.getParentFile(localAbspath); } DirParsedInfo dirInfo = db.obtainWcRoot(wriPath); SVNWCDbRoot root = dirInfo.wcDbDir.getWCRoot(); File localRelpath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), localAbspath.getAbsolutePath())); Structure<ExternalNodeInfo> externalInfo = Structure.obtain(ExternalNodeInfo.class); externalInfo.set(ExternalNodeInfo.revision, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.changedRevision, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.reposId, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.recordedRevision, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.recordedPegRevision, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.kind, SVNWCDbKind.Dir); externalInfo.set(ExternalNodeInfo.presence, SVNWCDbStatus.Normal); externalInfo.set(ExternalNodeInfo.reposRootUrl, reposRootUrl); externalInfo.set(ExternalNodeInfo.reposUuid, reposUuid); externalInfo.set(ExternalNodeInfo.recordAncestorRelPath, SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), recordAncestorAbspath.getAbsolutePath()))); externalInfo.set(ExternalNodeInfo.recordedReposRelPath, recordedReposRelPath); externalInfo.set(ExternalNodeInfo.recordedPegRevision, recordedPegRevision); externalInfo.set(ExternalNodeInfo.recordedRevision, recordedRevision); externalInfo.set(ExternalNodeInfo.workItems, workItems); begingWriteTransaction(root); try { insertExternalNode(root, localRelpath, externalInfo); } catch (SVNException e) { rollbackTransaction(root); throw e; } finally { commitTransaction(root); externalInfo.release(); } } public static void insertExternalNode(SVNWCDbRoot root, File localRelpath, Structure<ExternalNodeInfo> info) throws SVNException { long reposId = info.lng(ExternalNodeInfo.reposId); if (reposId == SVNWCContext.INVALID_REVNUM) { reposId = root.getDb().createReposId(root.getSDb(), info.<SVNURL>get(ExternalNodeInfo.reposRootUrl), info.text(ExternalNodeInfo.reposUuid)); } boolean updateRoot; SVNWCDbStatus status; try { WCDbBaseInfo baseInfo = root.getDb().getBaseInfo(root, localRelpath, BaseInfoField.updateRoot, BaseInfoField.status); updateRoot = baseInfo.updateRoot; status = baseInfo.status; if (status == SVNWCDbStatus.Normal && !updateRoot) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_UNEXPECTED_STATUS); SVNErrorManager.error(err, SVNLogType.WC); } } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_PATH_NOT_FOUND) { throw e; } } SVNWCDbKind kind = info.<SVNWCDbKind>get(ExternalNodeInfo.kind); if (kind == SVNWCDbKind.File || kind == SVNWCDbKind.Symlink) { InsertBase insertBase = root.getDb().new InsertBase(); insertBase.localRelpath = localRelpath; insertBase.status = SVNWCDbStatus.Normal; insertBase.kind = info.<SVNWCDbKind>get(ExternalNodeInfo.kind); insertBase.reposId = reposId; insertBase.reposRelpath = info.<File>get(ExternalNodeInfo.reposRelPath); insertBase.revision = info.lng(ExternalNodeInfo.revision); insertBase.props = info.<SVNProperties>get(ExternalNodeInfo.properties); insertBase.changedRev = info.lng(ExternalNodeInfo.changedRevision); insertBase.changedDate = info.<SVNDate>get(ExternalNodeInfo.changedDate); insertBase.changedAuthor = info.text(ExternalNodeInfo.changedAuthor); insertBase.davCache = info.<SVNProperties>get(ExternalNodeInfo.davCache); insertBase.checksum = info.<SvnChecksum>get(ExternalNodeInfo.checksum); insertBase.target = info.<File>get(ExternalNodeInfo.target); insertBase.conflict = info.<SVNSkel>get(ExternalNodeInfo.conflict); insertBase.updateActualProps = info.is(ExternalNodeInfo.updateActualProperties); insertBase.actualProps = info.<SVNProperties>get(ExternalNodeInfo.newActualProperties); insertBase.keepRecordedInfo = info.is(ExternalNodeInfo.keepRecordedInfo); insertBase.workItems = info.<SVNSkel>get(ExternalNodeInfo.workItems); insertBase.fileExternal = true; insertBase.iprops = info.<Map<String, SVNProperties>>get(ExternalNodeInfo.iprops); insertBase.wcId = root.getWcId(); insertBase.wcRoot = root; try { insertBase.transaction(root.getSDb()); } catch (SqlJetException e) { sqliteError(e); } } else { root.getDb().addWorkQueue(root.getAbsPath(), info.<SVNSkel>get(ExternalNodeInfo.workItems)); } // SVNSqlJetInsertStatement stmt = new InsertExternalStatement(root.getSDb()); try { stmt.bindf("issttsisii", root.getWcId(), localRelpath, SVNFileUtil.getFileDir(localRelpath), getPresenceText(info.<SVNWCDbStatus>get(ExternalNodeInfo.presence)), getKindText(info.<SVNWCDbKind>get(ExternalNodeInfo.kind)), info.get(ExternalNodeInfo.recordAncestorRelPath), reposId, info.get(ExternalNodeInfo.recordedReposRelPath), info.lng(ExternalNodeInfo.recordedPegRevision), info.lng(ExternalNodeInfo.recordedRevision)); stmt.done(); } finally { stmt.reset(); } } public static void removeExternal(SVNWCContext context, File wriAbsPath, File localAbsPath) throws SVNException { Structure<ExternalNodeInfo> info = readExternal(context, localAbsPath, wriAbsPath, ExternalNodeInfo.presence, ExternalNodeInfo.kind); removeExternalNode(context, localAbsPath, wriAbsPath, null); SVNWCDbKind kind = info.<SVNWCDbKind>get(ExternalNodeInfo.kind); info.release(); if (kind == SVNWCDbKind.Dir) { CheckWCRootInfo wcRootInfo = context.checkWCRoot(localAbsPath, false); if (wcRootInfo != null && wcRootInfo.wcRoot) { context.removeFromRevisionControl(localAbsPath, true, false); } } else { try { WCDbBaseInfo baseInfo = context.getDb().getBaseInfo(localAbsPath, BaseInfoField.updateRoot); if (baseInfo != null && !baseInfo.updateRoot) { return; } } catch (SVNException e) { if (e.getErrorMessage().getErrorCode() != SVNErrorCode.WC_PATH_NOT_FOUND) { throw e; } } context.getDb().removeBase(localAbsPath); SVNFileUtil.deleteFile(localAbsPath); } } public static void removeExternalNode(SVNWCContext context, File localAbsPath, File wriAbsPath, SVNSkel workItems) throws SVNException { if (wriAbsPath == null) { wriAbsPath = SVNFileUtil.getParentFile(localAbsPath); } DirParsedInfo dirInfo = ((SVNWCDb) context.getDb()).obtainWcRoot(wriAbsPath); SVNWCDbRoot root = dirInfo.wcDbDir.getWCRoot(); File localRelpath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), localAbsPath.getAbsolutePath())); begingWriteTransaction(root); SVNSqlJetDeleteStatement deleteExternal = null; try { deleteExternal = new SVNSqlJetDeleteStatement(root.getSDb(), SVNWCDbSchema.EXTERNALS); try { deleteExternal.bindf("is", root.getWcId(), localRelpath); deleteExternal.done(); } finally { deleteExternal.reset(); } if (workItems != null) { root.getDb().addWorkQueue(root.getAbsPath(), workItems); } } catch (SVNException e) { rollbackTransaction(root); } finally { commitTransaction(root); } } public static Structure<ExternalNodeInfo> readExternal(SVNWCContext context, File localAbsPath, File wriAbsPath, ExternalNodeInfo... fields) throws SVNException { if (wriAbsPath == null) { wriAbsPath = SVNFileUtil.getParentFile(localAbsPath); } DirParsedInfo dirInfo = ((SVNWCDb) context.getDb()).obtainWcRoot(wriAbsPath); SVNWCDbRoot root = dirInfo.wcDbDir.getWCRoot(); File localRelpath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), localAbsPath.getAbsolutePath())); SVNSqlJetSelectStatement selectExternalInfo = new SVNSqlJetSelectStatement(root.getSDb(), SVNWCDbSchema.EXTERNALS); try { selectExternalInfo.bindf("is", root.getWcId(), localRelpath); if (selectExternalInfo.next()) { Structure<ExternalNodeInfo> info = Structure.obtain(ExternalNodeInfo.class, fields); if (info.hasField(ExternalNodeInfo.presence)) { info.set(ExternalNodeInfo.presence, getColumnPresence(selectExternalInfo, EXTERNALS__Fields.presence)); } if (info.hasField(ExternalNodeInfo.kind)) { info.set(ExternalNodeInfo.kind, getColumnKind(selectExternalInfo, EXTERNALS__Fields.kind)); } if (info.hasField(ExternalNodeInfo.definingAbsPath)) { info.set(ExternalNodeInfo.definingAbsPath, SVNFileUtil.createFilePath(root.getAbsPath(), selectExternalInfo.getColumnString(EXTERNALS__Fields.def_local_relpath))); } // TODO read more return info; } else { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.WC_PATH_NOT_FOUND, "The node ''{0}'' is not an external.", localAbsPath); SVNErrorManager.error(err, SVNLogType.WC); } } finally { reset(selectExternalInfo); } return null; } /** * INSERT OR REPLACE INTO externals ( * wc_id, local_relpath, parent_relpath, presence, kind, def_local_relpath, * repos_id, def_repos_relpath, def_operational_revision, def_revision) * VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10) */ private static class InsertExternalStatement extends SVNSqlJetInsertStatement { public InsertExternalStatement(SVNSqlJetDb sDb) throws SVNException { super(sDb, SVNWCDbSchema.EXTERNALS, SqlJetConflictAction.REPLACE); } @Override protected Map<String, Object> getInsertValues() throws SVNException { Map<String, Object> values = new HashMap<String, Object>(); values.put(EXTERNALS__Fields.wc_id.toString(), getBind(1)); values.put(EXTERNALS__Fields.local_relpath.toString(), getBind(2)); values.put(EXTERNALS__Fields.parent_relpath.toString(), getBind(3)); values.put(EXTERNALS__Fields.presence.toString(), getBind(4)); values.put(EXTERNALS__Fields.kind.toString(), getBind(5)); values.put(EXTERNALS__Fields.def_local_relpath.toString(), getBind(6)); values.put(EXTERNALS__Fields.repos_id.toString(), getBind(7)); values.put(EXTERNALS__Fields.def_repos_relpath.toString(), getBind(8)); if (((Long) getBind(9)) >= 0) { values.put(EXTERNALS__Fields.def_operational_revision.toString(), getBind(9)); } else { values.put(EXTERNALS__Fields.def_operational_revision.toString(), null); } if (((Long) getBind(10)) >= 0) { values.put(EXTERNALS__Fields.def_revision.toString(), getBind(10)); } else { values.put(EXTERNALS__Fields.def_revision.toString(), null); } return values; } } public static void addExternalFile(SVNWCContext context, File localAbsPath, File wriAbsPath, File reposRelPath, SVNURL reposRootUrl, String reposUuid, long targetRevision, SVNProperties newPristineProperties, Map<String, SVNProperties> iprops, long changedRev, SVNDate changedDate, String changedAuthor, SvnChecksum newChecksum, SVNProperties davCache, File recordAncestorAbspath, File recordedReposRelPath, long recordedPegRevision, long recordedRevision, boolean updateActualProperties, SVNProperties newActualProperties, boolean keepRecordedInfo, SVNSkel conflictSkel, SVNSkel allWorkItems) throws SVNException { SVNWCDb db = (SVNWCDb) context.getDb(); if (wriAbsPath == null) { wriAbsPath = SVNFileUtil.getParentFile(localAbsPath); } DirParsedInfo dirInfo = db.obtainWcRoot(wriAbsPath); SVNWCDbRoot root = dirInfo.wcDbDir.getWCRoot(); File localRelpath = SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), localAbsPath.getAbsolutePath())); Structure<ExternalNodeInfo> externalInfo = Structure.obtain(ExternalNodeInfo.class); externalInfo.set(ExternalNodeInfo.kind, SVNWCDbKind.File); externalInfo.set(ExternalNodeInfo.presence, SVNWCDbStatus.Normal); externalInfo.set(ExternalNodeInfo.reposRootUrl, reposRootUrl); externalInfo.set(ExternalNodeInfo.reposUuid, reposUuid); externalInfo.set(ExternalNodeInfo.reposId, SVNWCContext.INVALID_REVNUM); externalInfo.set(ExternalNodeInfo.reposRelPath, reposRelPath); externalInfo.set(ExternalNodeInfo.revision, targetRevision); externalInfo.set(ExternalNodeInfo.properties, newPristineProperties); externalInfo.set(ExternalNodeInfo.iprops, iprops); externalInfo.set(ExternalNodeInfo.changedRevision, changedRev); externalInfo.set(ExternalNodeInfo.changedDate, changedDate); externalInfo.set(ExternalNodeInfo.changedAuthor, changedAuthor); externalInfo.set(ExternalNodeInfo.checksum, newChecksum); externalInfo.set(ExternalNodeInfo.davCache, davCache); externalInfo.set(ExternalNodeInfo.recordAncestorRelPath, SVNFileUtil.createFilePath(SVNPathUtil.getRelativePath(root.getAbsPath().getAbsolutePath(), recordAncestorAbspath.getAbsolutePath()))); externalInfo.set(ExternalNodeInfo.recordedRevision, recordedRevision); externalInfo.set(ExternalNodeInfo.recordedPegRevision, recordedPegRevision); externalInfo.set(ExternalNodeInfo.recordedReposRelPath, recordedReposRelPath); externalInfo.set(ExternalNodeInfo.updateActualProperties, updateActualProperties); externalInfo.set(ExternalNodeInfo.newActualProperties, newActualProperties); externalInfo.set(ExternalNodeInfo.keepRecordedInfo, keepRecordedInfo); externalInfo.set(ExternalNodeInfo.conflict, conflictSkel); externalInfo.set(ExternalNodeInfo.workItems, allWorkItems); begingWriteTransaction(root); try { insertExternalNode(root, localRelpath, externalInfo); } catch (SVNException e) { rollbackTransaction(root); throw e; } finally { commitTransaction(root); externalInfo.release(); } } }