/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2019, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2019 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #ifndef _TFREVISIONCONTROL_H_INCLUDED_ #define _TFREVISIONCONTROL_H_INCLUDED_ #include "TfSchemaManager.h" #include "DbObjectIterator.h" #include "ThreadsCounter.h" #define STL_USING_MAP #include "OdaSTL.h" #include /** \details Declares merge policy types. Merge policy determines conflict resolution action, when automatic resolution fails. Manual assumes some kind of user interaction — not implemented yet. */ enum OdTfMergePolicy { kOdTfMergePreferTheirs, // Use data from the target branch kOdTfMergePreferMine, // Use data from the source branch kOdTfMergeManual // Let the user decide which branch data to use }; /** \details This structure stores hash codes for commits. */ struct OdTfDigest { char data[20]; void write(OdStreamBuf* pBuf) const { pBuf->putBytes(data, 20); } void read(OdStreamBuf* pBuf) { pBuf->getBytes(data, 20); } bool operator < (const OdTfDigest& other) const { return memcmp(data, other.data, 20) < 0; } bool operator == (const OdTfDigest& other) const { return memcmp(data, other.data, 20) == 0; } bool operator != (const OdTfDigest& other) const { return memcmp(data, other.data, 20) != 0; } static OdTfDigest kNull() { OdTfDigest res; memset(res.data, 0, 20); return res; } bool isNull() const { char test[20] = { 0 }; return memcmp(test, data, 20) == 0; } }; /** \details Structure describing a commit in the revision control database. \remarks Array of parent commits contains one record for usual commit and several for merge commit. In case of merge commit, the first record in the array corresponds to the target branch, i.e. the branch into which the merge was done. */ struct TFDLL_EXPORT OdTfCommitInfo { OdTimeStamp date; // Commit timestamp OdString message; // Commit message OdString author; // Commit author OdArray parents; // An array of parent commits OdStreamBufPtr userData; // Arbitrary user data OdTfCommitInfo(const OdString& author = L"", const OdString& message = L"", const OdTimeStamp& date = OdTimeStamp(OdTimeStamp::kInitUniversalTime), OdStreamBuf* arbitraryUserData = 0); }; typedef OdArray OdDbHandleArray; namespace OdTfRevisionControl { /** \details Imports a .dwg database to a .dsf storage. Without optional parameters this function is expected to be used for the initial import to an empty storage (automatically switches to the specified branch). \param pStream [in] A stream associated with the storage. \param pDb [in] A database to be imported to the storage. \param branch [in] Branch name. \param message [in] Commit information. */ TFDLL_EXPORT void import(OdStreamBuf* pStream, OdDbDatabase* pDb, const OdString& branch = L"master", const OdTfCommitInfo& message = OdTfCommitInfo()); /** \details Imports a database from a .dwg file to a revision control storage in a .dsf file as a commit to the specified branch (automatically switches to the specified branch). Imports the given database as if its current state is the next revision of the given branch. This function is expected to be used for integrating changes that were made in third-party editors. \param pDbTo [in] A database which storage the commit will be made to. \param pDbFrom [in] A database to be imported as a new commit. \param branch [in] Branch name. \param message [in] Commit information. */ TFDLL_EXPORT void importAsCommit(OdDbDatabase* pDbTo, OdDbDatabase* pDbFrom, const OdString& branch = L"master", const OdTfCommitInfo& message = OdTfCommitInfo()); /** \details Reads a database from a storage. A database is checked out from the tip of the source branch. A "localBranch" parameter sets a default branch for commit. The source branch is saved as default branch for merge (like remote tracking, for 'pull'). If "partial" is false, all the objects are loaded in memory. If they will be eventually loaded anyway, it is much faster not to set "partial" flag to true. \param strm [in] A stream associated with the storage to checkout from. \param pHostApp [in] Platform specific host application services. \param localBranch [in] A branch to be set as current for commits. \param sourceBranch [in] A source branch to checkout a database from. \param partial [in] Flag that determines whether all the objects are loaded in memory (false) or not (true). \returns A pointer to the database corresponding to a checked out state. */ TFDLL_EXPORT OdDbDatabasePtr checkout(OdStreamBuf* strm, OdDbHostAppServices* pHostApp, const OdString& localBranch, const OdString& sourceBranch = L"master", bool partial = false); /** \details Creates a link between an empty database and a storage. Updates the database from the "sourceBranch" branch of the storage. Sets "localBranch" as the current branch for commits. If "partial" is false, all the objects are loaded in memory. If they will be eventually loaded anyway, it is much faster not to set "partial" flag to true. \remarks The database must be empty (created by default). \param pDb [in] An empty database to be updated from the storage. \param strg [in] A stream associated with the storage to checkout from. \param pHostApp [in] Platform specific host application services. \param localBranch [in] A branch to be set as current for commits. \param sourceBranch [in] A source branch to checkout a database from. \param partial [in] Flag that determines whether all the objects are loaded in memory (false) or not (true). */ TFDLL_EXPORT void checkout(OdDbDatabase* pDb, OdStreamBuf* strg, OdDbHostAppServices* pHostApp, const OdString& localBranch, const OdString& sourceBranch = L"master", bool partial = false); /** \details Creates a new database and updates it from the storage, associated with the source database. \param pSourceDb [in] A database which storage will be used to checkout from. \param pHostApp [in] Platform specific host application services. \param localBranch [in] A branch to be set as current for commits. \param sourceBranch [in] A source branch to checkout a database from. \param partial [in] Flag that determines whether all the objects are loaded in memory (false) or not (true). \returns A pointer to the database corresponding to a checked out state. */ TFDLL_EXPORT OdDbDatabasePtr checkoutInDatabase(const OdDbDatabase * pSourceDb, OdDbHostAppServices* pHostApp, const OdString & localBranch, const OdString & sourceBranch, bool partial = false); /** \details Saves changes in the database to the storage, creates a commit object and shifts the current branch tip. Optional parameters "mergeCommitOtherBranch" and "mergeCommitOtherParent" are for merge commits (record the result of a merge operation). The "objectsToSave" optional parameter is a list of objects to save. It is used to perform a partial commit. \param pDb [in] The database, which state has to be saved. \param message [in] Commit message. \param mergeCommitOtherBranch [in] The name of the branch to save merge commit in. Optional. Used for merge commits. \param mergeCommitOtherParent [in] The name of the branch to be saved as parent for the current merge commit branch. Optional. Used for merge commits. \param objectsToSave [in] A list of objects to be saved. Optional. Used to perform a partial commit. \returns A hash code of a commit. */ TFDLL_EXPORT OdTfDigest commit(OdDbDatabase* pDb, const OdTfCommitInfo& message, const OdString& mergeCommitOtherBranch = OdString::kEmpty, OdTfDigest* mergeCommitOtherParent = 0, const OdDbObjectIdArray* objectsToSave = 0); /** \details Merges changes from the storage to the database. If branch name is not specified, a source branch for merging is the branch which this database was checked out from (like "git pull"). Merge operation does not automatically commit changes, only runtime database is changed. \remarks If merge was fast forward, no merge commit is necessary. If "noFastForward" flag is true, and the remote branch is directly above or below this one in the commit graph, the function does nothing. \param pDb [in] A database to merge into. \param conflicts [out] An array of objects having conflicts. \param mp [in] Merge policy in case of a conflict. \param branch [in] Branch to be used as a source for merge. \param noFastForward [in] Flag that prohibits fast forward merging (when true). \returns False if merge was fast forward; true otherwise. */ TFDLL_EXPORT bool merge(OdDbDatabase* pDb, OdDbHandleArray& conflicts, OdTfMergePolicy mp = kOdTfMergePreferTheirs, const OdString& branch = OdString::kEmpty, bool noFastForward = false); /** \details Gets the hash code and information about the commit on the tip of the specified branch. \param pDb [in] A database which storage to get a branch tip from. \param branch [in] Branch name to get a tip of. \param sha [out] Hash code of the branch tip commit. \param commit [out] Information about the branch tip commit. \returns True if the branch was found; false otherwise. */ TFDLL_EXPORT bool getBranchTip(OdDbDatabase* pDb, const OdString& branch, OdTfDigest& sha, OdTfCommitInfo* commit = 0); /** \details Returns the name of the current working branch. \param pDb [in] A database to get the working branch from. \param head [out] Hash code of the branch head commit. \remarks If no revision control storage is associated with the database, returns OdString::kEmpty. \returns Current working branch name. */ TFDLL_EXPORT OdString getCurrentBranch(OdDbDatabase* pDb, OdTfDigest* head = 0); /** \details Returns commit information of a specific revision having the corresponding hash code, from the storage of a specified database. \param pDb [in] A database to get the commit information from. \param sha [in] Hash code of a commit to get information about. \returns Commit information of the revision with the corresponding hash code. */ TFDLL_EXPORT OdTfCommitInfo getCommitInfo(OdDbDatabase* pDb, const OdTfDigest& sha); /** \details Collects all the changes made from one revision to another and writes them to a patch file. A starting revision is supposed to be the ancestor of an ending revision. Together with the applyPatch() function it is designed to transfer changes between storages. \param pDb [in] A database to be used as the source for a patch. \param from [in] Hash code of the starting revision. \param to [in] Hash code of the ending revision. \returns A pointer to a stream buffer associated with the patch file. */ TFDLL_EXPORT OdStreamBufPtr makePatch(OdDbDatabase* pDb, const OdTfDigest& from, const OdTfDigest& to); /** \details Applies the patch created by makePatch() function on a storage to get all the changes contained in the patch file transfered to the specified branch in the storage. \remarks The applyPatch() function will fail if the branch tip is not at the same revision as the patch starting revision is. (makePatch "from" parameter) \param pDb [in] A database which storage the patch is applied to. \param s [in] A stream buffer associated with the patch file. \param branch [in] Name of the branch to transfer changes into. */ TFDLL_EXPORT void applyPatch(OdDbDatabase* pDb, OdStreamBuf* s, const OdString& branch); /** \details Automatically processes all applying patch routines in case of the destination branch tip is not at the same revision as the patch starting revision is. These include resetting the destination branch to the required revision, creating a new branch, applying a patch to the newly created branch and merging it with the destination branch. \param pDb [in] A database which storage the patch is applied to. \param s [in] A stream buffer associated with the patch file. \param conflicts [out] An array of objects having conflicts. \param mp [in] Merge policy in case of a conflict. \param sourceBranch [in] Name of the branch to transfer changes into. \param localBranch [in] Name of the temporary branch. Optional. */ TFDLL_EXPORT void applyPatchViaBranch(OdDbDatabase* pDb, OdStreamBuf* s, OdDbHandleArray& conflicts, OdTfMergePolicy mp, const OdString& sourceBranch, const OdString& localBranch = OdString::kEmpty); /** \details Sets the branch tip to the revision with the given hash. If no other branch points to the current branch tip, and you don't have it saved, it becomes inaccessible. If no branch with the given name exists, it is created. \param pDb [in] A database in which storage the branch will be reset or created. \param branch [in] A branch name to be reset or created. \param sha [in] Hash code of the revision to be set as the tip of the branch. \returns True if a branch was created, false otherwise. */ TFDLL_EXPORT bool resetBranch(OdDbDatabase* pDb, const OdString& branch, const OdTfDigest& sha, bool saveChanges = true); /** \details Updates the database to the revision on the tip of the specified branch and makes this branch default for commits. All uncommitted changes in the runtime database will be lost. This behavior can be modified by setting the "hard" flag. If "hard" is set to false and there are non-committed changes in the database, operation will fail. If "hard" is true (default), all non-committed changes will be lost. \param pDb [in] A database which storage to switch the branch in. \param branchName [in] The name of the branch to switch to. \param hard [in] A flag that defines the behavior of the function if there are non-committed changes in the database. */ TFDLL_EXPORT void switchBranch(OdDbDatabase* pDb, const OdString& branchName, bool hard = true); /** \details Gets a list of objects that were changed since the last commit. \param pDb [in] A database to get the list of changes. \returns An array of object IDs. */ TFDLL_EXPORT OdDbObjectIdArray getLocalChanges(OdDbDatabase* pDb); /** \details This wrapper over the OdDbDatabase::writeFile() method preserves the connection between the drawing database and the revision control storage. Using the OdDbDatabase::writeFile() method instead of this function will sever the connection. \param pDb [in] A database to be exported. \param pStreamBuf [in] A stream buffer, associated with a drawing file. \param fileVersion [in] The version of the resulting file. \param saveThumbnailImage [in] A flag defining whether the thumbnail image should be saved to the resulting file. */ TFDLL_EXPORT void exportDwg(OdDbDatabase* pDb, OdStreamBuf* pStreamBuf, OdDb::DwgVersion fileVersion, bool saveThumbnailImage = false); /** \details This wrapper over the OdDbDatabase::writeFile() method preserves the connection between the drawing database and the revision control storage. Using the OdDbDatabase::writeFile() method instead of this function will sever the connection. \param pDb [in] A database to be exported. \param pStreamBuf [in] A stream buffer, associated with a drawing file. \param fileVersion [in] The version of the resulting file. \param saveThumbnailImage [in] A flag defining whether the thumbnail image should be saved to the resulting file. \param dxfPrecision [in] The floating-point precision of the .dxf file in decimal places. Maximum value is 16 (default). */ TFDLL_EXPORT void exportDxf(OdDbDatabase* pDb, OdStreamBuf* pStreamBuf, OdDb::DwgVersion fileVersion, bool saveThumbnailImage = false, int dxfPrecision = 16); /** \details Declares change types. */ enum ChangeType { kObjectAdded = 1, // Object added to database. kObjectDeleted, // Object deleted from database. kObjectModified // Object modified. }; typedef std::map ChangeList; /** \details Gets a list of handles of the objects that differ between revisions. Revisions may actually be unrelated. \param pDb [in] A database which storage to get the list of differences from. \param newRevision [in] Hash code of the first revision. \param oldRevision [in] Hash code of the second revision. \param result [out] A list of changes, containing IDs of objects that differ between revisions. */ TFDLL_EXPORT void getRevisionDifference(OdDbDatabase* pDb, const OdTfDigest& newRevision, const OdTfDigest& oldRevision, ChangeList& result); typedef std::map BranchList; /** \details Gets a list of the branches contained in the revision control storage of a database. \param pTf [in] A database which storage to get a list of the branches from. \param list [out] A list of the branches. \returns True if the storage was processed successfully; false otherwise. */ TFDLL_EXPORT bool getBranchList(OdDbDatabase* pTf, BranchList& list); /** \details Compresses data stored in the revision control storage. In the initial, non-compressed state, each revision in the storage contains full state of objects that were changed. Compression reduces the size of the storage by removing the full state object snapshots and replacing them with the information containing differences of the object from the previous revision (so called deltas). Some of the revisions remain uncompressed (so called reference revisions). This is intended to reduce the number of processed revisions to restore the required state of the database, and thus increase the speed of switching between revisions. \remarks Once compressed, a storage cannot be decompressed. \param pDb [in] A database which revision control storage to be compressed. \param referenceDistance [in] Distance between reference revisions (in revisions). Lesser distance results in worse compression but faster intermediate revision retrieval. \param auditCompressedData [in] Performs verification of compressed revisions by uncompressing them and comparing with the original. */ TFDLL_EXPORT void compressRevisionData(OdDbDatabase* pDb, OdUInt16 referenceDistance = 10, const bool auditCompressedData = true); /** \details Loads objects from the storage if earlier a partial checkout was performed. \remarks This function is designed to run in a separate thread. \param pDb [in] A database to load objects to. \param pObjects [in] An iterator containing a list of objects to be loaded. \param pReactor [in] A reactor for multi-threaded loading. Optional. */ TFDLL_EXPORT void loadObjects(OdDbDatabase* pDb, OdDbObjectIterator* pObjects, OdMTLoadReactor* pReactor = 0); /** \details Begins partial import of the database into the revision control storage if the full import cannot be performed or not needed. \remarks Branch name and commit information are default. \param pStream [in] A stream associated with the storage. \param pDb [in] A database to be imported to the storage. */ TFDLL_EXPORT void beginPartialImport(OdStreamBuf* pStream, OdDbDatabase* pDb); /** \details Imports an object to the storage. \remarks Used only with beginPartialImport() and endPartialImport(). \param id [in] Id of the object to be imported to the storage. \param pageObjectToDisk [in] If true (default) flushes the stream buffer to the file after importing the object. */ TFDLL_EXPORT void writeObjectPartial(OdDbObjectId id, bool pageObjectToDisk = true); /** \details Ends partial import to the revision control storage creating a first revision. \param pDb [in] A database to end the partial import. */ TFDLL_EXPORT void endPartialImport(OdDbDatabase* pDb); /** \details Flushes stream buffer to file and releases the revision control storage file. \param pDb [in] A database to detach the storage from. */ TFDLL_EXPORT void detachStorage(OdDbDatabase* pDb); }; #endif //_TFREVISIONCONTROL_H_INCLUDED_