/////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////// #include "TfRevModule.h" #include "DbCircle.h" #include "DbBlockTableRecord.h" #include "DebugStuff.h" #include "MemoryStream.h" ODRX_DEFINE_DYNAMIC_MODULE(OdRcModule); void OdRcCommit::execute(OdEdCommandContext* pCmdCtx) { OdDbDatabase* pDb = OdDbCommandContextPtr(pCmdCtx)->database(); OdString msg = pCmdCtx->userIO()->getString(L"Enter commit message", OdEd::kGstAllowSpaces); OdTfRevisionControl::commit(pDb, OdTfCommitInfo(L"client", msg)); } /** \details Send code to stop server. */ void OdRcStop::execute(OdEdCommandContext* pCmdCtx) { OdDbDatabase* pDb = OdDbCommandContextPtr(pCmdCtx)->database(); void* context = 0; void* socket = 0; try { initZMQ(context, socket); send(socket, kOdRcStop, 0); } catch (OdException& e) { pCmdCtx->userIO()->putString(e.description()); } catch (...) { pCmdCtx->userIO()->putString(L"unknown connection error"); } zmq_close(socket); zmq_ctx_destroy(context); } /** \details Send set of commits to server (like git push) */ void OdRcPush::execute(OdEdCommandContext* pCmdCtx) { OdDbDatabase* pDb = OdDbCommandContextPtr(pCmdCtx)->database(); void* context = 0; void* socket = 0; try { initZMQ(context, socket); OdTfDigest shaLastPush, shaLastPull, shaTo; OdTfRevisionControl::getBranchTip(pDb, OdTfRevisionControl::getCurrentBranch(pDb), shaTo); shaLastPush = _module->getShaLastPush(); shaLastPull = _module->getShaLastPull(); if (shaLastPush == shaTo || shaTo.isNull()) { ODA_FAIL_M("No a new data to push\n"); pCmdCtx->userIO()->putString(L"No a new data to push"); return; } send(socket, kOdRcPush); OdTfDigest dig; receive(socket, dig.data, sizeof(dig.data)); OdRcCodes code; if (dig != shaLastPull && shaLastPush == shaLastPull) { code = kOdRcNeedPull; send(socket, code); throw OdError(L"Remote repository ahead, need pull"); } else send(socket, kOdRcOk, ZMQ_SNDMORE); OdStreamBufPtr sBuf = OdTfRevisionControl::makePatch(pDb, dig, shaTo); sendBigData(socket, sBuf); receive(socket, code); if (code != kOdRcOk) { ODA_FAIL(); } _module->setShaLastPull(shaTo); _module->setShaLastPush(shaTo); } catch (OdException& e) { pCmdCtx->userIO()->putString(e.description()); } catch (...) { pCmdCtx->userIO()->putString(L"unknown connection error"); } zmq_close(socket); zmq_ctx_destroy(context); } void OdRcPull::execute(OdEdCommandContext* pCmdCtx) { OdDbDatabase* pDb = OdDbCommandContextPtr(pCmdCtx)->database(); void* context = 0; void* socket = 0; try { context = zmq_ctx_new(); initZMQ(context, socket); if (!OdTfRevisionControl::getCurrentBranch(pDb).isEmpty())//if found name - do pull, else do clone { send(socket, kOdRcPull, ZMQ_SNDMORE);//TODO need check, that database has one parent OdTfDigest sha = _module->getShaLastPull(); send(socket, 0, 0, sha.data, SHA_SIZE); OdRcCodes bAnswer; receive(socket, bAnswer); if (bAnswer == kOdRcNotOk || bAnswer != kOdRcOk) { pCmdCtx->userIO()->putString(L"Doesn't has new data"); return; } //receive size stream OdUInt64 N = 0; receive(socket, N); size_t length; zmq_msg_t reply; char* buf = new char[N]; for (int n = 0; N - n;)//receive bigData { zmq_msg_init(&reply); zmq_msg_recv(&reply, socket, 0); length = zmq_msg_size(&reply); if (length < 1) { ODA_ASSERT(length); zmq_msg_close(&reply); continue; } memcpy(buf + n, zmq_msg_data(&reply), length); n += (int)length; } zmq_msg_close(&reply); OdStreamBufPtr sBuf = OdFlatMemStream::createNew(buf, N); sBuf->rewind(); OdDbHandleArray hArr; OdTfRevisionControl::applyPatchViaBranch(pDb, sBuf, hArr, kOdTfMergePreferTheirs, OdTfRevisionControl::getCurrentBranch(pDb)); bool bMergeCommit = false; OdTfDigest sha2; OdTfRevisionControl::getBranchTip(pDb, OdTfRevisionControl::getCurrentBranch(pDb), sha2); _module->setShaLastPush(sha); _module->setShaLastPull(sha2); delete [] buf; } else//clone { pCmdCtx->userIO()->putString(L"Not found repository. Executed clone"); remove("repository.tig"); OdRcCodes code = kOdRcClone; send(socket, code, 0); receive(socket, code); if (code != kOdRcOk) { throw OdError(L"Something wrong on server"); } //TODO: message to user console, that base not created and we clone all base from server OdUInt64 N; receive(socket, N); zmq_msg_t reply; OdUInt64 length; unsigned char* buf = new unsigned char[N]; for (OdUInt64 n = 0; N - n;) { zmq_msg_init(&reply); zmq_msg_recv(&reply, socket, 0); length = zmq_msg_size(&reply); if (length < 1) { ODA_ASSERT(length); zmq_msg_close(&reply); continue; } memcpy(buf + n, zmq_msg_data(&reply), length); n += length; } zmq_msg_close(&reply); OdStreamBufPtr s = OdMemoryStream::createNew();//flat Memory not suitable s->putBytes(buf, N); OdTfRevisionControl::checkout(pDb, s, pDb->appServices(), L"master"); pDb->setMultiThreadedMode(OdDb::kMTLoading); bool bTest = pDb->isMultiThreadedMode(); OdDb::MultiThreadedMode test = pDb->multiThreadedMode(); s = 0; OdTfDigest sha; OdTfRevisionControl::getBranchTip(pDb, L"master", sha); _module->setShaLastPull(sha); _module->setShaLastPush(sha); delete[] buf;// ok? } } catch (OdException& e) { pCmdCtx->userIO()->putString(e.description()); } catch (...) { pCmdCtx->userIO()->putString(L"unknown connection error"); } zmq_close(socket); zmq_ctx_destroy(context); } void OdRcModule::initApp() { OdEdCommandStackPtr pCommands = odedRegCmds(); pCommands->addCommand(&m_RCCommit); pCommands->addCommand(&m_RCPush); pCommands->addCommand(&m_RCUpdate); pCommands->addCommand(&m_RCStop); m_RCCommit._module = this; m_RCUpdate._module = this; m_RCStop._module = this; m_RCPush._module = this; } void OdRcModule::uninitApp() { OdEdCommandStackPtr pCommands = odedRegCmds(); pCommands->removeGroup(L"Revision control git"); }