void SG_sync_remote__heartbeat( SG_context* pCtx, SG_repo* pRepo, SG_vhash** ppvh) { SG_vhash* pvh = NULL; char* pszRepoId = NULL; char* pszAdminId = NULL; char* pszHashMethod = NULL; SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh) ); SG_ERR_CHECK( SG_repo__get_repo_id(pCtx, pRepo, &pszRepoId) ); SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &pszAdminId) ); SG_ERR_CHECK( SG_repo__get_hash_method(pCtx, pRepo, &pszHashMethod) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__REPO_ID, pszRepoId) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__ADMIN_ID, pszAdminId) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__HASH_METHOD, pszHashMethod) ); *ppvh = pvh; pvh = NULL; /* fall through */ fail: SG_VHASH_NULLFREE(pCtx, pvh); SG_NULLFREE(pCtx, pszRepoId); SG_NULLFREE(pCtx, pszAdminId); SG_NULLFREE(pCtx, pszHashMethod); }
void u0038_test_wdmapping(SG_context * pCtx) { SG_vhash* pvh = NULL; SG_pathname* pPath = NULL; SG_pathname* pMappedPath = NULL; SG_string* pstrRepoDescriptorName = NULL; char* pszidGid = NULL; VERIFY_ERR_CHECK_DISCARD( SG_PATHNAME__ALLOC(pCtx, &pPath) ); VERIFY_ERR_CHECK_DISCARD( SG_pathname__set__from_cwd(pCtx, pPath) ); VERIFY_ERR_CHECK_DISCARD( SG_VHASH__ALLOC(pCtx, &pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvh, "hello", "world") ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvh, "hola", "mundo") ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "r1") ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add(pCtx, "r1", pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_workingdir__set_mapping(pCtx, pPath, "r1", NULL) ); VERIFY_ERR_CHECK_DISCARD( SG_workingdir__find_mapping(pCtx, pPath, &pMappedPath, &pstrRepoDescriptorName, &pszidGid) ); VERIFY_COND("ridesc match", (0 == strcmp("r1", SG_string__sz(pstrRepoDescriptorName)))); VERIFY_ERR_CHECK_DISCARD( SG_pathname__append__from_sz(pCtx, pPath, "foo") ); VERIFY_ERR_CHECK_DISCARD( SG_pathname__append__from_sz(pCtx, pPath, "bar") ); VERIFY_ERR_CHECK_DISCARD( SG_pathname__append__from_sz(pCtx, pPath, "plok") ); SG_STRING_NULLFREE(pCtx, pstrRepoDescriptorName); SG_PATHNAME_NULLFREE(pCtx, pMappedPath); VERIFY_ERR_CHECK_DISCARD( SG_workingdir__find_mapping(pCtx, pPath, &pMappedPath, &pstrRepoDescriptorName, &pszidGid) ); SG_STRING_NULLFREE(pCtx, pstrRepoDescriptorName); SG_PATHNAME_NULLFREE(pCtx, pMappedPath); SG_PATHNAME_NULLFREE(pCtx, pPath); SG_VHASH_NULLFREE(pCtx, pvh); }
void SG_workingdir__set_mapping( SG_context* pCtx, const SG_pathname* pPathLocalDirectory, const char* pszNameRepoInstanceDescriptor, /**< The name of the repo instance descriptor */ const char* pszidGidAnchorDirectory /**< The GID of the directory within the repo to which this is anchored. Usually it's user root. */ ) { SG_vhash* pvhNew = NULL; SG_vhash* pvh = NULL; SG_pathname* pMyPath = NULL; SG_pathname* pDrawerPath = NULL; SG_pathname* pMappingFilePath = NULL; SG_NULLARGCHECK_RETURN(pPathLocalDirectory); SG_NULLARGCHECK_RETURN(pszNameRepoInstanceDescriptor); /* make a copy of the path so we can modify it (adding the final slash) */ SG_ERR_CHECK( SG_PATHNAME__ALLOC__COPY(pCtx, &pMyPath, pPathLocalDirectory) ); /* null the original parameter pointer to make sure we don't use it anymore */ pPathLocalDirectory = NULL; /* make sure the path we were given is a directory that exists */ SG_ERR_CHECK( SG_fsobj__verify_directory_exists_on_disk__pathname(pCtx, pMyPath) ); /* it's a directory, so it should have a final slash */ SG_ERR_CHECK( SG_pathname__add_final_slash(pCtx, pMyPath) ); /* make sure the name of the repo instance descriptor is valid */ SG_ERR_CHECK( SG_closet__descriptors__get(pCtx, pszNameRepoInstanceDescriptor, &pvh) ); SG_VHASH_NULLFREE(pCtx, pvh); // TODO verify that the anchor GID is valid for that repo? SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhNew) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhNew, "descriptor", pszNameRepoInstanceDescriptor) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhNew, "anchor", pszidGidAnchorDirectory) ); SG_ERR_CHECK( SG_workingdir__verify_drawer_exists(pCtx, pMyPath, &pDrawerPath) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pMappingFilePath, pDrawerPath, "repo.json") ); SG_ERR_CHECK( SG_vfile__update__vhash(pCtx, pMappingFilePath, "mapping", pvhNew) ); SG_VHASH_NULLFREE(pCtx, pvhNew); SG_PATHNAME_NULLFREE(pCtx, pMyPath); SG_PATHNAME_NULLFREE(pCtx, pDrawerPath); SG_PATHNAME_NULLFREE(pCtx, pMappingFilePath); return; fail: SG_PATHNAME_NULLFREE(pCtx, pDrawerPath); SG_PATHNAME_NULLFREE(pCtx, pMappingFilePath); SG_PATHNAME_NULLFREE(pCtx, pMyPath); SG_VHASH_NULLFREE(pCtx, pvhNew); SG_VHASH_NULLFREE(pCtx, pvh); }
/** * Select an appropriate difftool to use on this file. * We require that the common and right-side fields of * pvhDiffItem be filled in first. (The left-side fields * can be after this is called.) * */ static void _pick_tool(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, SG_vhash * pvhDiffItem, SG_string * pStringHeader) { SG_filetool * pTool = NULL; const char * pszRepoPath_live = NULL; const char * pszAbsPath = NULL; SG_pathname * pPathname = NULL; const char * pszToolNameChosen = NULL; SG_bool bIsTmp_right = SG_FALSE; // use the suffix on the (always present) live-repo-path (rather than // the left- or right- version) to pick a tool. // // if that fails, use the suffix of current file in the WD // (provided it isn't a temp file). the left side is always // a temp file, so don't bother with it. SG_ERR_CHECK( SG_vhash__check__sz(pCtx, pvhItem, "path", &pszRepoPath_live) ); SG_ERR_CHECK( SG_vhash__check__bool(pCtx, pvhDiffItem, "right_is_temp", &bIsTmp_right) ); if (!bIsTmp_right) { SG_ERR_CHECK( SG_vhash__check__sz(pCtx, pvhDiffItem, "right_abs_path", &pszAbsPath) ); if (pszAbsPath) SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &pPathname, pszAbsPath) ); } SG_ERR_CHECK( SG_difftool__select(pCtx, pData->pszDiffToolContext, // gui or console pszRepoPath_live, // current/live repo-path pPathname, // live or temp absolute pathname pData->pszTool, // suggested/requested tool pData->pWcTx->pDb->pRepo, &pTool) ); if (pTool) { SG_ERR_CHECK( SG_filetool__get_name(pCtx, pTool, &pszToolNameChosen) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "tool", pszToolNameChosen) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "context", pData->pszDiffToolContext) ); } else { SG_ERR_CHECK( SG_string__append__format(pCtx, pStringHeader, "=== No difftool configured for ('%s', '%s') in context '%s'.\n", pszRepoPath_live, pszAbsPath, pData->pszDiffToolContext) ); } fail: SG_FILETOOL_NULLFREE(pCtx, pTool); SG_PATHNAME_NULLFREE(pCtx, pPathname); }
/** * For MODIFIED or DELETED items we need to populate the left side * of the diff. This should be called after _pick_tool(). * * put the various fields that we need to use in the call to SG_difftool__run() * into the pvhDiffItem for later. * */ static void _get_left_side_details(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, SG_vhash * pvhDiffItem) { SG_string * pStringLabel_left = NULL; SG_pathname * pPathAbsolute_left = NULL; SG_vhash * pvhSubsection_left = NULL; // we do not own this const char * pszRepoPath_left; const char * pszGid; const char * pszHid_left; const char * pszToolName = NULL; const char * pszName_left; // get the repo-path for the left side *AS IT EXISTED IN THE LEFT CSET*. SG_ERR_CHECK( SG_vhash__get__vhash(pCtx, pvhItem, pData->pszSubsectionLeft, &pvhSubsection_left) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhSubsection_left, "hid", &pszHid_left) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhSubsection_left, "path", &pszRepoPath_left) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhSubsection_left, "name", &pszName_left) ); // left label is "<left_repo-path> <hid>" (we have an HID and since no date makes sense) SG_ERR_CHECK( sg_wc_diff_utils__make_label(pCtx, pszRepoPath_left, pszHid_left, NULL, &pStringLabel_left) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "left_label", SG_string__sz(pStringLabel_left)) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhDiffItem, "tool", &pszToolName) ); if (strcmp(pszToolName, SG_DIFFTOOL__INTERNAL__SKIP) == 0) { // There's no point in exporting a binary file into TEMP so // that we can invoke a no-op difftool. // See W5937. } else { // fetch the baseline version of the file into a temp file. // the left side should be read-only because it refers to a // historical version (regardless of whether or not we are // interactive). SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhItem, "gid", &pszGid) ); SG_ERR_CHECK( sg_wc_diff_utils__export_to_temp_file(pCtx, pData->pWcTx, pData->pszSubsectionLeft, pszGid, pszHid_left, pszName_left, &pPathAbsolute_left) ); SG_ERR_CHECK( SG_fsobj__chmod__pathname(pCtx, pPathAbsolute_left, 0400) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "left_abs_path", SG_pathname__sz(pPathAbsolute_left)) ); } fail: SG_PATHNAME_NULLFREE(pCtx, pPathAbsolute_left); SG_STRING_NULLFREE(pCtx, pStringLabel_left); }
void u0025_vhash__create(SG_context * pCtx, SG_vhash** pph) { SG_vhash* ph = NULL; SG_varray* pa = NULL; SG_vhash* pvhSub = NULL; SG_varray* pvaSub = NULL; SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &ph) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, ph, "hello", "world") ); SG_ERR_CHECK( SG_VARRAY__ALLOC(pCtx, &pa) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pa, 31) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pa, 51) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhSub) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhSub, "not", "now") ); SG_ERR_CHECK( SG_varray__append__vhash(pCtx, pa, &pvhSub) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pa, 71) ); SG_ERR_CHECK( SG_VARRAY__ALLOC(pCtx, &pvaSub) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pvaSub, 81) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pvaSub, 82) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pvaSub, 83) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pvaSub, 84) ); SG_ERR_CHECK( SG_varray__append__varray(pCtx, pa, &pvaSub) ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pa, 91) ); SG_ERR_CHECK( SG_vhash__add__varray(pCtx, ph, "a", &pa) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, ph, "b", "fiddle") ); *pph = ph; return; fail: // TODO free return; }
void SG_vc_hooks__ASK__WIT__LIST_ITEMS( SG_context* pCtx, SG_repo* pRepo, const char * psz_search_term, SG_varray *pBugs ) { SG_vhash* pvh_params = NULL; SG_vhash* pvh_result = NULL; SG_vhash* pvh_hook = NULL; const char* psz_js = NULL; const char* psz_descriptor_name = NULL; SG_bool hasBugs = SG_FALSE; SG_ERR_CHECK( sg_vc_hooks__lookup_by_interface__single_result( pCtx, pRepo, SG_VC_HOOK__INTERFACE__ASK__WIT__LIST_ITEMS, &pvh_hook ) ); if (!pvh_hook) return; SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_hook, "js", &psz_js) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh_params) ); SG_ERR_CHECK( SG_repo__get_descriptor_name(pCtx, pRepo, &psz_descriptor_name) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "descriptor_name", psz_descriptor_name) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "text", psz_search_term) ); SG_ERR_CHECK( SG_vc_hooks__execute(pCtx, psz_js, pvh_params, &pvh_result) ); SG_ERR_CHECK( SG_vhash__has(pCtx, pvh_result, "items", &hasBugs) ); if (hasBugs && pBugs) { SG_varray *bugs = NULL; SG_ERR_CHECK( SG_vhash__get__varray(pCtx, pvh_result, "items", &bugs) ); SG_ERR_CHECK( SG_varray__copy_items(pCtx, bugs, pBugs) ); } fail: SG_VHASH_NULLFREE(pCtx, pvh_params); SG_VHASH_NULLFREE(pCtx, pvh_result); SG_VHASH_NULLFREE(pCtx, pvh_hook); }
void SG_dbrecord__add_pair(SG_context* pCtx, SG_dbrecord* prec, const char* putf8Name, const char* putf8Value) { if (prec->pid) { SG_ERR_THROW_RETURN(SG_ERR_INVALID_WHILE_FROZEN); } SG_ERR_CHECK_RETURN( SG_vhash__add__string__sz(pCtx, prec->pvh, putf8Name, putf8Value) ); }
void SG_dagfrag__to_vhash__shared(SG_context * pCtx, SG_dagfrag * pFrag, SG_vhash * pvhShared, SG_vhash ** ppvhNew) { SG_vhash * pvhFrag = NULL; SG_varray * pvaMyData = NULL; struct _serialize_data serialize_data; SG_NULLARGCHECK_RETURN(pFrag); SG_NULLARGCHECK_RETURN(ppvhNew); SG_ASSERT( (! IS_TRANSIENT(pFrag)) ); SG_ERR_CHECK( SG_VHASH__ALLOC__SHARED(pCtx,&pvhFrag,5,pvhShared) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx,pvhFrag,KEY_REPO_ID,pFrag->m_sz_repo_id) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx,pvhFrag,KEY_ADMIN_ID,pFrag->m_sz_admin_id) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx,pvhFrag,KEY_DAGNUM,(SG_int64)pFrag->m_iDagNum) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx,pvhFrag,KEY_VERSION,VALUE_VERSION) ); SG_ERR_CHECK( SG_VARRAY__ALLOC(pCtx,&pvaMyData) ); serialize_data.pvhFrag = pvhFrag; serialize_data.pvaMyData = pvaMyData; // walk the complete RB_Cache and add complete info for each my_data item // (regardless of whether the dagnode is a START or INTERIOR member or in // the END-FRINGE. These will be in an essentially random order (HID). SG_ERR_CHECK( SG_rbtree__foreach(pCtx, pFrag->m_pRB_Cache, _serialize_data_cb, &serialize_data) ); SG_ERR_CHECK( SG_vhash__add__varray(pCtx,pvhFrag,KEY_DATA,&pvaMyData) ); *ppvhNew = pvhFrag; return; fail: SG_VHASH_NULLFREE(pCtx, pvhFrag); SG_VARRAY_NULLFREE(pCtx, pvaMyData); }
void MyFn(create_repo)(SG_context * pCtx, SG_repo ** ppRepo) { // caller must free returned value. SG_repo * pRepo; SG_pathname * pPathnameRepoDir = NULL; SG_vhash* pvhPartialDescriptor = NULL; char buf_repo_id[SG_GID_BUFFER_LENGTH]; char buf_admin_id[SG_GID_BUFFER_LENGTH]; char* pszRepoImpl = NULL; VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_repo_id, sizeof(buf_repo_id)) ); VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_admin_id, sizeof(buf_admin_id)) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC(pCtx, &pPathnameRepoDir) ); VERIFY_ERR_CHECK( SG_pathname__set__from_cwd(pCtx, pPathnameRepoDir) ); VERIFY_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhPartialDescriptor) ); VERIFY_ERR_CHECK_DISCARD( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__NEWREPO_DRIVER, NULL, &pszRepoImpl, NULL) ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_KEY__STORAGE, pszRepoImpl) ); VERIFY_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_FSLOCAL__PATH_PARENT_DIR, SG_pathname__sz(pPathnameRepoDir)) ); VERIFY_ERR_CHECK( SG_repo__create_repo_instance(pCtx,pvhPartialDescriptor,SG_TRUE,NULL,buf_repo_id,buf_admin_id,&pRepo) ); SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); { const SG_vhash * pvhRepoDescriptor = NULL; VERIFY_ERR_CHECK( SG_repo__get_descriptor(pCtx, pRepo,&pvhRepoDescriptor) ); //INFOP("open_repo",("Repo is [%s]",SG_string__sz(pstrRepoDescriptor))); } *ppRepo = pRepo; fail: SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); SG_PATHNAME_NULLFREE(pCtx, pPathnameRepoDir); SG_NULLFREE(pCtx, pszRepoImpl); }
void MyFn(create_repo)(SG_context * pCtx, SG_repo** ppRepo) { SG_repo* pRepo = NULL; SG_pathname* pPath_repo = NULL; char buf_repo_id[SG_GID_BUFFER_LENGTH]; char buf_admin_id[SG_GID_BUFFER_LENGTH]; SG_vhash* pvhPartialDescriptor = NULL; char* pszRepoImpl = NULL; VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_repo_id, sizeof(buf_repo_id)) ); VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_admin_id, sizeof(buf_admin_id)) ); /* Get our paths fixed up */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC(pCtx, &pPath_repo) ); VERIFY_ERR_CHECK( SG_pathname__set__from_cwd(pCtx, pPath_repo) ); VERIFY_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pPath_repo, "repo") ); SG_fsobj__mkdir__pathname(pCtx, pPath_repo); SG_context__err_reset(pCtx); // Create the repo VERIFY_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhPartialDescriptor) ); VERIFY_ERR_CHECK_DISCARD( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__NEWREPO_DRIVER, NULL, &pszRepoImpl, NULL) ); if (pszRepoImpl) { VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_KEY__STORAGE, pszRepoImpl) ); } VERIFY_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_FSLOCAL__PATH_PARENT_DIR, SG_pathname__sz(pPath_repo)) ); VERIFY_ERR_CHECK( SG_repo__create_repo_instance(pCtx,NULL,pvhPartialDescriptor,SG_TRUE,NULL,buf_repo_id,buf_admin_id,&pRepo) ); *ppRepo = pRepo; // Fall through to common cleanup fail: SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); SG_PATHNAME_NULLFREE(pCtx, pPath_repo); SG_NULLFREE(pCtx, pszRepoImpl); }
void u0038_test_ridesc(SG_context * pCtx) { SG_vhash* pvh = NULL; SG_vhash* pvh2 = NULL; SG_vhash* pvh_all = NULL; SG_uint32 count = 0; VERIFY_ERR_CHECK_DISCARD( SG_VHASH__ALLOC(pCtx, &pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvh, "hello", "world") ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvh, "hola", "mundo") ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "1") ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add(pCtx, "1", pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__remove(pCtx, "1") ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "2") ); /* This may or may not be an error */ /* delete one that is not there should be an error */ VERIFY_ERR_CHECK_HAS_ERR_DISCARD( SG_closet__descriptors__remove(pCtx, "2") ); /* fetch one that is not there should be an error */ VERIFY_ERR_CHECK_HAS_ERR_DISCARD( SG_closet__descriptors__get(pCtx, "2", &pvh2) ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "3") ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "4") ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add(pCtx, "3", pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add(pCtx, "4", pvh) ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__get(pCtx, "3", &pvh2) ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__list(pCtx, &pvh_all) ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__count(pCtx, pvh_all, &count) ); VERIFY_COND("count", (count >= 2)); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "3") ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "4") ); SG_VHASH_NULLFREE(pCtx, pvh_all); SG_VHASH_NULLFREE(pCtx, pvh); SG_VHASH_NULLFREE(pCtx, pvh2); }
/** * For MODIFIED or ADDED items we need to populate the right side * of the diff. * * See footnote 1 above for bIsTmp_right. * */ static void _get_right_side_details(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, sg_wc_liveview_item * pLVI, SG_vhash * pvhDiffItem) { SG_string * pStringLabel_right = NULL; SG_pathname * pPathAbsolute_right = NULL; SG_vhash * pvhSubsection_right = NULL; // we do not own this const char * pszRepoPath_right; char bufDate[SG_TIME_FORMAT_LENGTH+1]; SG_bool bIsTmp_right; SG_fsobj_stat st_right; // get the repo-path for the right side *AS IT EXISTED IN THE RIGHT CSET*. SG_ERR_CHECK( SG_vhash__get__vhash(pCtx, pvhItem, pData->pszSubsectionRight, &pvhSubsection_right) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhSubsection_right, "path", &pszRepoPath_right) ); SG_ERR_CHECK( sg_wc_liveview_item__get_proxy_file_path(pCtx, pLVI, pData->pWcTx, &pPathAbsolute_right, &bIsTmp_right) ); SG_ERR_CHECK( SG_fsobj__stat__pathname(pCtx, pPathAbsolute_right, &st_right) ); SG_ERR_CHECK( SG_time__format_utc__i64(pCtx, st_right.mtime_ms, bufDate, SG_NrElements(bufDate)) ); // the right label is "<right_repo_path> <datestamp>" SG_ERR_CHECK( SG_fsobj__stat__pathname(pCtx, pPathAbsolute_right, &st_right) ); SG_ERR_CHECK( sg_wc_diff_utils__make_label(pCtx, pszRepoPath_right, NULL, bufDate, &pStringLabel_right) ); // put the various fields that we need to use in the call to SG_difftool__run() // into the pvhDiffItem for later. SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "right_label", SG_string__sz(pStringLabel_right)) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "right_abs_path", SG_pathname__sz(pPathAbsolute_right)) ); SG_ERR_CHECK( SG_vhash__add__bool( pCtx, pvhDiffItem, "right_is_tmp", bIsTmp_right) ); fail: SG_PATHNAME_NULLFREE(pCtx, pPathAbsolute_right); SG_STRING_NULLFREE(pCtx, pStringLabel_right); }
void SG_localsettings__factory__list__vhash( SG_context* pCtx, SG_vhash** ppvh ) { SG_uint32 i = 0; SG_vhash* pvh = NULL; SG_varray* pva = NULL; SG_ERR_CHECK( SG_vhash__alloc(pCtx, &pvh) ); for (i=0; i<(sizeof(g_factory_defaults) / sizeof(struct localsetting_factory_default)); i++) { if (SG_VARIANT_TYPE_SZ == g_factory_defaults[i].type) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, g_factory_defaults[i].psz_path_partial, g_factory_defaults[i].psz_val) ); } else if (SG_VARIANT_TYPE_VARRAY == g_factory_defaults[i].type) { const char** pp_el = NULL; SG_ERR_CHECK( SG_varray__alloc(pCtx, &pva) ); pp_el = g_factory_defaults[i].pasz_array; while (*pp_el) { SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva, *pp_el) ); pp_el++; } SG_ERR_CHECK( SG_vhash__add__varray(pCtx, pvh, g_factory_defaults[i].psz_path_partial, &pva) ); } else { SG_ERR_THROW( SG_ERR_NOTIMPLEMENTED ); } } *ppvh = pvh; pvh = NULL; fail: SG_VHASH_NULLFREE(pCtx, pvh); }
/** * A DELETED file is present in the baseline and is not present in the WD. * Let the difftool have a generated TEMPFILE for the historical left side * and a NULL for the right side file. * * We expect that the difftool will simply print the entire baseline file * with '<' or '-' in front of each line. * */ static void _diff__file__deleted(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, SG_vhash * pvhDiffItem, SG_string * pStringHeader) { SG_string * pStringLabel_right = NULL; // the file does not exist in the right cset, so any repo-path label // we make for the right side is a bit bogus. SG_ERR_CHECK( sg_wc_diff_utils__make_label(pCtx, "(not present)", NULL, NULL, &pStringLabel_right) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "right_label", SG_string__sz(pStringLabel_right)) ); SG_ERR_CHECK( _pick_tool(pCtx, pData, pvhItem, pvhDiffItem, pStringHeader) ); SG_ERR_CHECK( _get_left_side_details(pCtx, pData, pvhItem, pvhDiffItem) ); fail: SG_STRING_NULLFREE(pCtx, pStringLabel_right); }
static void _serialize_data_cb(SG_context * pCtx, const char * szHid, void * pAssocData, void * pVoidSerializeData) { struct _serialize_data * pSerializeData = (struct _serialize_data *)pVoidSerializeData; _my_data * pMyData = (_my_data *)pAssocData; SG_vhash * pvhMyData = NULL; SG_vhash * pvhDagnode = NULL; SG_ERR_CHECK( SG_VHASH__ALLOC__SHARED(pCtx,&pvhMyData,5,pSerializeData->pvhFrag) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx,pvhMyData,KEY_DFS_STATE,(SG_int64)pMyData->m_state) ); if (SG_DFS_END_FRINGE == pMyData->m_state) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx,pvhMyData,KEY_DAGNODE_ID,szHid) ); } else { SG_ERR_CHECK( SG_dagnode__to_vhash__shared(pCtx,pMyData->m_pDagnode,pvhMyData,&pvhDagnode) ); SG_ERR_CHECK( SG_vhash__add__vhash(pCtx,pvhMyData,KEY_ACTUAL_DAGNODE,&pvhDagnode) ); } #if DEBUG && TRACE_DAGFRAG && 0 SG_ERR_CHECK( SG_vhash_debug__dump_to_console(pCtx, pvhMyData) ); #endif SG_ERR_CHECK( SG_varray__append__vhash(pCtx,pSerializeData->pvaMyData,&pvhMyData) ); return; fail: SG_VHASH_NULLFREE(pCtx, pvhMyData); SG_VHASH_NULLFREE(pCtx, pvhDagnode); }
void sg_wc_tx__diff__setup__file(SG_context * pCtx, sg_wc6diff__setup_data * pData, const SG_vhash * pvhItem, SG_wc_status_flags statusFlags) { SG_string * pStringHeader = NULL; SG_vhash * pvhDiffItem = NULL; // we do not own this const char * pszGid; // we do not own this const char * pszLiveRepoPath; // we do not own this SG_vhash * pvhItemStatus; // we do not own this if (statusFlags & SG_WC_STATUS_FLAGS__U__IGNORED) { // The code in wc4status won't create header info for ignored // items unless verbose is set and diff never sets it, so we // skip this item to avoid getting the divider row of equal signs. return; } SG_ERR_CHECK( SG_varray__appendnew__vhash(pCtx, pData->pvaDiffSteps, &pvhDiffItem) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhItem, "gid", &pszGid) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "gid", pszGid) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhItem, "path", &pszLiveRepoPath) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "path", pszLiveRepoPath) ); SG_ERR_CHECK( SG_vhash__get__vhash(pCtx, pvhItem, "status", &pvhItemStatus) ); SG_ERR_CHECK( SG_vhash__addcopy__vhash(pCtx, pvhDiffItem, "status", pvhItemStatus) ); // the following if-else-if-else... DOES NOT imply that these statuses // are mutually exclusive (for example, one could have ADDED+LOST), but // rather just the cases when we actually want to print the content diffs. if (statusFlags & SG_WC_STATUS_FLAGS__A__SPARSE) { SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_string__append__format(pCtx, pStringHeader, "=== %s\n", "Omitting details for sparse item.") ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else if (statusFlags & SG_WC_STATUS_FLAGS__U__LOST) { SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_string__append__format(pCtx, pStringHeader, "=== %s\n", "Omitting details for lost item.") ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else if (statusFlags & SG_WC_STATUS_FLAGS__U__FOUND) { // just build the header -- we never include content details for an uncontrolled item. SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else if ((statusFlags & SG_WC_STATUS_FLAGS__S__MERGE_CREATED) && (statusFlags & SG_WC_STATUS_FLAGS__S__DELETED)) { // just build the header -- no content to diff -- not present now and not present in baseline SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else if ((statusFlags & SG_WC_STATUS_FLAGS__S__UPDATE_CREATED) && (statusFlags & SG_WC_STATUS_FLAGS__S__DELETED)) { // just build the header -- no content to diff -- not present now and not present in baseline SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else if (statusFlags & (SG_WC_STATUS_FLAGS__S__ADDED |SG_WC_STATUS_FLAGS__S__MERGE_CREATED |SG_WC_STATUS_FLAGS__S__UPDATE_CREATED |SG_WC_STATUS_FLAGS__S__DELETED |SG_WC_STATUS_FLAGS__C__NON_DIR_MODIFIED)) { // content added/deleted/changed. SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( _diff__file__contents(pCtx, pData, pvhItem, statusFlags, pvhDiffItem, pStringHeader) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } else { // just build the header -- content did not change -- must be a simple structural change. SG_ERR_CHECK( sg_wc_tx__diff__setup__header(pCtx, pvhItem, &pStringHeader) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhDiffItem, "header", SG_string__sz(pStringHeader)) ); } fail: SG_STRING_NULLFREE(pCtx, pStringHeader); }
// TODO not sure we really want to pass this much stuff to this interface void SG_vc_hooks__ASK__WIT__VALIDATE_ASSOCIATIONS( SG_context* pCtx, SG_repo* pRepo, const char* const* paszAssocs, SG_uint32 count_assocs, SG_varray *pBugs ) { SG_vhash* pvh_params = NULL; SG_vhash* pvh_result = NULL; char* psz_repo_id = NULL; char* psz_admin_id = NULL; SG_vhash* pvh_hook = NULL; const char* psz_js = NULL; SG_uint32 i = 0; SG_varray* pva_ids = NULL; const char* psz_descriptor_name = NULL; SG_ERR_CHECK( sg_vc_hooks__lookup_by_interface__single_result( pCtx, pRepo, SG_VC_HOOK__INTERFACE__ASK__WIT__VALIDATE_ASSOCIATIONS, &pvh_hook ) ); if (!pvh_hook) return; SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id) ); SG_ERR_CHECK( SG_repo__get_repo_id( pCtx, pRepo, &psz_repo_id ) ); SG_ERR_CHECK( SG_repo__get_descriptor_name(pCtx, pRepo, &psz_descriptor_name) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_hook, "js", &psz_js) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh_params) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "repo_id", psz_repo_id) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "admin_id", psz_admin_id) ); if (psz_descriptor_name) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "descriptor_name", psz_descriptor_name) ); } SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pvh_params, "wit_ids", &pva_ids) ); for (i=0; i<count_assocs; i++) { SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva_ids, paszAssocs[i]) ); } SG_ERR_CHECK( SG_vc_hooks__execute(pCtx, psz_js, pvh_params, &pvh_result) ); // TODO process the result if (pvh_result) { SG_bool hasErrors = SG_FALSE; SG_bool hasBugs = SG_FALSE; SG_ERR_CHECK( SG_vhash__has(pCtx, pvh_result, "error", &hasErrors) ); if (hasErrors) { const char *emsg = NULL; SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_result, "error", &emsg) ); SG_ERR_THROW2( SG_ERR_VC_HOOK_REFUSED, (pCtx, "%s", emsg) ); } SG_ERR_CHECK( SG_vhash__has(pCtx, pvh_result, "bugs", &hasBugs) ); if (hasBugs && pBugs) { SG_varray *bugs = NULL; SG_ERR_CHECK( SG_vhash__get__varray(pCtx, pvh_result, "bugs", &bugs) ); SG_ERR_CHECK( SG_varray__copy_items(pCtx, bugs, pBugs) ); } } fail: SG_VHASH_NULLFREE(pCtx, pvh_params); SG_VHASH_NULLFREE(pCtx, pvh_result); SG_VHASH_NULLFREE(pCtx, pvh_hook); SG_NULLFREE(pCtx, psz_repo_id); SG_NULLFREE(pCtx, psz_admin_id); }
void SG_vc_hooks__BROADCAST__AFTER_COMMIT( SG_context* pCtx, SG_repo* pRepo, SG_changeset* pcs, const char* psz_tied_branch_name, const SG_audit* pq, const char* psz_comment, const char* const* paszAssocs, SG_uint32 count_assocs, const SG_stringarray* psa_stamps ) { SG_varray* pva_hooks = NULL; SG_vhash* pvh_params = NULL; char* psz_repo_id = NULL; char* psz_admin_id = NULL; SG_ERR_CHECK( SG_vc_hooks__lookup_by_interface( pCtx, pRepo, SG_VC_HOOK__INTERFACE__BROADCAST__AFTER_COMMIT, &pva_hooks ) ); if (pva_hooks) { SG_uint32 count_hooks = 0; SG_uint32 i_hook = 0; const char* psz_descriptor_name = NULL; SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id) ); SG_ERR_CHECK( SG_repo__get_repo_id( pCtx, pRepo, &psz_repo_id ) ); SG_ERR_CHECK( SG_repo__get_descriptor_name(pCtx, pRepo, &psz_descriptor_name) ); SG_ERR_CHECK( SG_varray__count(pCtx, pva_hooks, &count_hooks) ); for (i_hook=0; i_hook<count_hooks; i_hook++) { SG_vhash* pvh_hook = NULL; const char* psz_js = NULL; const char* psz_csid = NULL; SG_vhash* pvh_changeset = NULL; SG_ERR_CHECK( SG_varray__get__vhash(pCtx, pva_hooks, i_hook, &pvh_hook) ); SG_ERR_CHECK( SG_changeset__get_id_ref(pCtx, pcs, &psz_csid) ); SG_ERR_CHECK( SG_changeset__get_vhash_ref(pCtx, pcs, &pvh_changeset) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_hook, "js", &psz_js) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh_params) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "csid", psz_csid) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "repo_id", psz_repo_id) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "admin_id", psz_admin_id) ); if (psz_descriptor_name) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "descriptor_name", psz_descriptor_name) ); } if (pq) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "userid", pq->who_szUserId) ); } if (psz_comment) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "comment", psz_comment) ); } if (psz_tied_branch_name) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "branch", psz_tied_branch_name) ); } SG_ERR_CHECK( SG_vhash__addcopy__vhash(pCtx, pvh_params, "changeset", pvh_changeset) ); if (paszAssocs && count_assocs) { SG_uint32 i = 0; SG_varray* pva_ids = NULL; SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pvh_params, "wit_ids", &pva_ids) ); for (i=0; i<count_assocs; i++) { SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva_ids, paszAssocs[i]) ); } } if (psa_stamps) { SG_uint32 count = 0; SG_uint32 i = 0; SG_varray* pva_stamps = NULL; SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pvh_params, "stamps", &pva_stamps) ); SG_ERR_CHECK( SG_stringarray__count(pCtx, psa_stamps, &count) ); for (i=0; i<count; i++) { const char* psz_stamp = NULL; SG_ERR_CHECK( SG_stringarray__get_nth(pCtx, psa_stamps, i, &psz_stamp) ); SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva_stamps, psz_stamp) ); } } SG_ERR_CHECK( SG_vc_hooks__execute(pCtx, psz_js, pvh_params, NULL) ); SG_VHASH_NULLFREE(pCtx, pvh_params); } } fail: SG_VHASH_NULLFREE(pCtx, pvh_params); SG_VARRAY_NULLFREE(pCtx, pva_hooks); SG_NULLFREE(pCtx, psz_repo_id); SG_NULLFREE(pCtx, psz_admin_id); }
/** * Deal with the status for 1 item and accumulate * the result in pvaStatus. * */ static void _sg_wc_tx__status(SG_context * pCtx, SG_wc_tx * pWcTx, SG_varray * pvaStatus, const char * pszInput, SG_uint32 depth, SG_bool bListUnchanged, SG_bool bNoIgnores, SG_bool bNoTSC, SG_bool bListSparse, SG_bool bListReserved, SG_vhash ** ppvhLegend) { SG_string * pStringRepoPath = NULL; sg_wc_liveview_item * pLVI; // we do not own this SG_bool bKnown; char chDomain; SG_vhash * pvhCSets = NULL; SG_vhash * pvhLegend = NULL; const char * pszWasLabel_l = "Baseline (B)"; const char * pszWasLabel_r = "Working"; SG_NULLARGCHECK_RETURN( pWcTx ); SG_NULLARGCHECK_RETURN( pvaStatus ); // pszInput is optional -- if omitted, we assume "@/". // ppvhLegend is optional SG_ERR_CHECK( sg_wc_db__path__anything_to_repopath(pCtx, pWcTx->pDb, pszInput, SG_WC_DB__PATH__IMPORT_FLAGS__TREAT_NULL_AS_ROOT, &pStringRepoPath, &chDomain) ); #if TRACE_WC_TX_STATUS SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "SG_wc_tx__status: '%s' normalized to [domain %c] '%s'\n", pszInput, chDomain, SG_string__sz(pStringRepoPath)) ); #endif SG_ERR_CHECK( sg_wc_tx__liveview__fetch_item__domain(pCtx, pWcTx, pStringRepoPath, &bKnown, &pLVI) ); if (!bKnown) { // We only get this if the path is completely bogus and // took us off into the weeds (as opposed to reporting // something just not-controlled). SG_ERR_THROW2( SG_ERR_NOT_FOUND, (pCtx, "Unknown item '%s'.", SG_string__sz(pStringRepoPath)) ); } SG_ERR_CHECK( sg_wc_tx__rp__status__lvi(pCtx, pWcTx, pLVI, depth, bListUnchanged, bNoIgnores, bNoTSC, bListSparse, bListReserved, pszWasLabel_l, pszWasLabel_r, pvaStatus) ); #if TRACE_WC_TX_STATUS SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "SG_wc_tx__status: computed status [depth %d][bListUnchanged %d][bNoIgnores %d][bNoTSC %d][bListSparse %d][bListReserved %d] on '%s':\n", depth, bListUnchanged, bNoIgnores, bNoTSC, bListSparse, bListReserved, SG_string__sz(pStringRepoPath)) ); SG_ERR_IGNORE( SG_varray_debug__dump_varray_of_vhashes_to_console(pCtx, pvaStatus, "") ); #endif if (ppvhLegend) { const char * pszHid_x; SG_ERR_CHECK( SG_wc_tx__get_wc_csets__vhash(pCtx, pWcTx, &pvhCSets) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhLegend) ); SG_ERR_CHECK( SG_vhash__check__sz(pCtx, pvhCSets, "A", &pszHid_x) ); if (pszHid_x) SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhLegend, "A", pszHid_x) ); SG_ERR_CHECK( SG_vhash__check__sz(pCtx, pvhCSets, "L0", &pszHid_x) ); if (pszHid_x) SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhLegend, "B", pszHid_x) ); SG_ERR_CHECK( SG_vhash__check__sz(pCtx, pvhCSets, "L1", &pszHid_x) ); if (pszHid_x) SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhLegend, "C", pszHid_x) ); #if TRACE_WC_TX_STATUS SG_ERR_IGNORE( SG_vhash_debug__dump_to_console__named(pCtx, pvhLegend, "Legend") ); #endif *ppvhLegend = pvhLegend; pvhLegend = NULL; } fail: SG_STRING_NULLFREE(pCtx, pStringRepoPath); SG_VHASH_NULLFREE(pCtx, pvhLegend); SG_VHASH_NULLFREE(pCtx, pvhCSets); }
void u0026_jsonparser__create_2(SG_context* pCtx, SG_string* pStr) { SG_jsonwriter* pjson = NULL; SG_vhash* pvh = NULL; SG_varray* pva = NULL; SG_uint32 i; char* pid = NULL; SG_ERR_CHECK( SG_jsonwriter__alloc(pCtx, &pjson, pStr) ); SG_ERR_CHECK( SG_jsonwriter__write_start_object(pCtx, pjson) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__string__sz(pCtx, pjson, "hello", "world") ); SG_ERR_CHECK( SG_jsonwriter__write_pair__int64(pCtx, pjson, "x", 5) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__double(pCtx, pjson, "pi", 3.14159) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__bool(pCtx, pjson, "b1", SG_TRUE) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__bool(pCtx, pjson, "b2", SG_FALSE) ); SG_ERR_CHECK( SG_jsonwriter__write_begin_pair(pCtx, pjson, "furball") ); SG_ERR_CHECK( SG_jsonwriter__write_start_array(pCtx, pjson) ); SG_ERR_CHECK( SG_jsonwriter__write_element__string__sz(pCtx, pjson, "plok") ); SG_ERR_CHECK( SG_jsonwriter__write_element__double(pCtx, pjson, 47.567) ); SG_ERR_CHECK( SG_jsonwriter__write_element__int64(pCtx, pjson, 22222) ); SG_ERR_CHECK( SG_jsonwriter__write_element__null(pCtx, pjson) ); SG_ERR_CHECK( SG_jsonwriter__write_element__bool(pCtx, pjson, SG_TRUE) ); SG_ERR_CHECK( SG_jsonwriter__write_element__bool(pCtx, pjson, SG_FALSE) ); SG_ERR_CHECK( SG_gid__alloc(pCtx, &pid) ); SG_ERR_CHECK( SG_jsonwriter__write_element__string__sz(pCtx, pjson, pid) ); SG_NULLFREE(pCtx, pid); SG_ERR_CHECK( SG_jsonwriter__write_end_array(pCtx, pjson) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__null(pCtx, pjson, "nope") ); SG_ERR_CHECK( SG_jsonwriter__write_pair__string__sz(pCtx, pjson, "messy", U0026_MESSY) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, "fried", "tomatoes") ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pvh, "q", 333) ); SG_ERR_CHECK( SG_jsonwriter__write_pair__vhash(pCtx, pjson, "sub", pvh) ); SG_VHASH_NULLFREE(pCtx, pvh); SG_ERR_CHECK( SG_VARRAY__ALLOC(pCtx, &pva) ); for (i=0; i<1000; i++) { SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva, "plok") ); SG_ERR_CHECK( SG_varray__append__int64(pCtx, pva, 22) ); SG_ERR_CHECK( SG_varray__append__double(pCtx, pva, 1.414) ); SG_ERR_CHECK( SG_varray__append__bool(pCtx, pva, SG_TRUE) ); SG_ERR_CHECK( SG_varray__append__bool(pCtx, pva, SG_FALSE) ); SG_ERR_CHECK( SG_varray__append__null(pCtx, pva) ); } SG_ERR_CHECK( SG_jsonwriter__write_pair__varray(pCtx, pjson, "a", pva) ); SG_VARRAY_NULLFREE(pCtx, pva); SG_ERR_CHECK( SG_jsonwriter__write_end_object(pCtx, pjson) ); SG_JSONWRITER_NULLFREE(pCtx, pjson); return; fail: SG_VHASH_NULLFREE(pCtx, pvh); SG_VARRAY_NULLFREE(pCtx, pva); SG_JSONWRITER_NULLFREE(pCtx, pjson); }
// TODO not sure we really want to pass this much stuff to this interface void SG_vc_hooks__ASK__WIT__ADD_ASSOCIATIONS( SG_context* pCtx, SG_repo* pRepo, SG_changeset* pcs, const char* psz_tied_branch_name, const SG_audit* pq, const char* psz_comment, const char* const* paszAssocs, SG_uint32 count_assocs, const SG_stringarray* psa_stamps ) { SG_vhash* pvh_hook = NULL; SG_vhash* pvh_params = NULL; SG_vhash* pvh_result = NULL; char* psz_repo_id = NULL; char* psz_admin_id = NULL; SG_ERR_CHECK( sg_vc_hooks__lookup_by_interface__single_result( pCtx, pRepo, SG_VC_HOOK__INTERFACE__ASK__WIT__ADD_ASSOCIATIONS, &pvh_hook ) ); if (pvh_hook) { const char* psz_js = NULL; SG_uint32 i = 0; SG_varray* pva_ids = NULL; const char* psz_descriptor_name = NULL; const char* psz_csid = NULL; SG_vhash* pvh_changeset = NULL; SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id) ); SG_ERR_CHECK( SG_repo__get_repo_id( pCtx, pRepo, &psz_repo_id ) ); SG_ERR_CHECK( SG_repo__get_descriptor_name(pCtx, pRepo, &psz_descriptor_name) ); SG_ERR_CHECK( SG_changeset__get_id_ref(pCtx, pcs, &psz_csid) ); SG_ERR_CHECK( SG_changeset__get_vhash_ref(pCtx, pcs, &pvh_changeset) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_hook, "js", &psz_js) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh_params) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "csid", psz_csid) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "repo_id", psz_repo_id) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "admin_id", psz_admin_id) ); if (psz_descriptor_name) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "descriptor_name", psz_descriptor_name) ); } if (pq) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "userid", pq->who_szUserId) ); } if (psz_comment) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "comment", psz_comment) ); } if (psz_tied_branch_name) { SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh_params, "branch", psz_tied_branch_name) ); } SG_ERR_CHECK( SG_vhash__addcopy__vhash(pCtx, pvh_params, "changeset", pvh_changeset) ); SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pvh_params, "wit_ids", &pva_ids) ); for (i=0; i<count_assocs; i++) { SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva_ids, paszAssocs[i]) ); } if (psa_stamps) { SG_uint32 count = 0; SG_uint32 i = 0; SG_varray* pva_stamps = NULL; SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pvh_params, "stamps", &pva_stamps) ); SG_ERR_CHECK( SG_stringarray__count(pCtx, psa_stamps, &count) ); for (i=0; i<count; i++) { const char* psz_stamp = NULL; SG_ERR_CHECK( SG_stringarray__get_nth(pCtx, psa_stamps, i, &psz_stamp) ); SG_ERR_CHECK( SG_varray__append__string__sz(pCtx, pva_stamps, psz_stamp) ); } } SG_ERR_CHECK( SG_vc_hooks__execute(pCtx, psz_js, pvh_params, &pvh_result) ); // TODO process the result if (pvh_result) { SG_bool hasErrors = SG_FALSE; SG_ERR_CHECK( SG_vhash__has(pCtx, pvh_result, "error", &hasErrors) ); if (hasErrors) { const char *emsg = NULL; SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_result, "error", &emsg) ); SG_ERR_THROW2( SG_ERR_VC_HOOK_REFUSED, (pCtx, "\n:%s: %s", SG_VC_HOOK__INTERFACE__ASK__WIT__ADD_ASSOCIATIONS, emsg) ); } } } fail: SG_VHASH_NULLFREE(pCtx, pvh_params); SG_VHASH_NULLFREE(pCtx, pvh_result); SG_VHASH_NULLFREE(pCtx, pvh_hook); SG_NULLFREE(pCtx, psz_repo_id); SG_NULLFREE(pCtx, psz_admin_id); }
void SG_sync_remote__push_clone__begin( SG_context* pCtx, const char* psz_repo_descriptor_name, const SG_vhash* pvhRepoInfo, const char** ppszCloneId) { const char* psz_repo_id = NULL; const char* psz_admin_id = NULL; const char* psz_hash_method = NULL; const char* pszRefValidatedName = NULL; SG_vhash* pvhFullDescriptor = NULL; // pNewRepo owns this. Don't free. SG_vhash* pvhDescriptorPartial = NULL; SG_closet_descriptor_handle* ph = NULL; SG_repo* pNewRepo = NULL; const char* pszRefCloneId = NULL; SG_NULLARGCHECK_RETURN(ppszCloneId); SG_ERR_CHECK_RETURN( _remote_clone_allowed(pCtx) ); /* We'll create a descriptor and empty repo immediately, so that we validate and claim the name * before a potentially long upload. */ SG_ERR_CHECK_RETURN( SG_vhash__get__sz(pCtx, pvhRepoInfo, SG_SYNC_REPO_INFO_KEY__REPO_ID, &psz_repo_id) ); SG_ERR_CHECK_RETURN( SG_vhash__get__sz(pCtx, pvhRepoInfo, SG_SYNC_REPO_INFO_KEY__ADMIN_ID, &psz_admin_id) ); SG_ERR_CHECK_RETURN( SG_vhash__get__sz(pCtx, pvhRepoInfo, SG_SYNC_REPO_INFO_KEY__HASH_METHOD, &psz_hash_method) ); SG_ERR_CHECK( SG_closet__descriptors__add_begin(pCtx, psz_repo_descriptor_name, NULL, psz_repo_id, psz_admin_id, &pszRefValidatedName, &pvhDescriptorPartial, &ph) ); SG_ERR_CHECK( SG_repo__create_repo_instance(pCtx, pszRefValidatedName, pvhDescriptorPartial, SG_TRUE, psz_hash_method, psz_repo_id, psz_admin_id, &pNewRepo) ); SG_VHASH_NULLFREE(pCtx, pvhDescriptorPartial); SG_ERR_CHECK_RETURN( SG_staging__clone__create(pCtx, psz_repo_descriptor_name, pvhRepoInfo, &pszRefCloneId) ); /* We temporarily add the clone ID to the repo descriptor so that we can verify * we're committing to the correct repo later, when the fragball's been uploaded. */ SG_ERR_CHECK( SG_repo__get_descriptor__ref(pCtx, pNewRepo, &pvhFullDescriptor) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhFullDescriptor, SG_SYNC_DESCRIPTOR_KEY__CLONE_ID, pszRefCloneId) ); SG_ERR_CHECK( SG_closet__descriptors__add_commit(pCtx, &ph, pvhFullDescriptor, SG_REPO_STATUS__CLONING) ); SG_REPO_NULLFREE(pCtx, pNewRepo); *ppszCloneId = pszRefCloneId; return; fail: SG_VHASH_NULLFREE(pCtx, pvhDescriptorPartial); SG_REPO_NULLFREE(pCtx, pNewRepo); SG_ERR_IGNORE( SG_closet__descriptors__add_abort(pCtx, &ph) ); }
static void _tree__add_next_node_to_results(SG_context * pCtx, _tree_t * pTree, SG_varray * pResults, SG_uint32 * pCountResults, SG_bool * pbLastResultWasIndented) { SG_vhash * pResult = NULL; SG_varray * pChildren = NULL; SG_uint32 i; SG_varray * pTmp = NULL; // Add pTree->pNextResult to results list. SG_ERR_CHECK( SG_varray__appendnew__vhash(pCtx, pResults, &pResult) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pResult, "revno", pTree->pNextResult->revno) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pResult, "changeset_id", pTree->pNextResult->pszHidRef) ); SG_ERR_CHECK( SG_vhash__add__vhash(pCtx, pResult, "parents", &pTree->pNextResult->pVcParents) ); SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pResult, "displayChildren", &pChildren) ); for(i=0; i<pTree->pNextResult->displayChildren.count; ++i) SG_ERR_CHECK( SG_varray__append__int64(pCtx, pChildren, pTree->pNextResult->displayChildren.p[i]->revno) ); if(pTree->pNextResult->displayChildren.count>1 && pTree->indentLevel>0) { SG_varray * pContinuationToken = NULL; SG_ERR_CHECK( SG_vhash__addnew__varray(pCtx, pResult, "continuationToken", &pContinuationToken) ); SG_ERR_CHECK( _tree__generate_continuation_token(pCtx, pTree, pContinuationToken) ); } SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pResult, "indent", pTree->indentLevel) ); *pbLastResultWasIndented = (pTree->indentLevel > 0); if(pTree->pNextResult->pDisplayParent!=NULL) { SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pResult, "displayParent", pTree->pNextResult->pDisplayParent->revno) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pResult, "indexInParent", pTree->pNextResult->pDisplayParent->displayChildren.count) ); SG_ASSERT(*pbLastResultWasIndented); } else { SG_ASSERT(!*pbLastResultWasIndented); } ++(*pCountResults); // Advance pTree->pNextResult pointer to next result. while(pTree->pNextResult->displayChildren.count==0 && pTree->pNextResult!=pTree->pRoot) { // We have already added this node and all children to the results. // Free the memory that will not be reused, and then put the node // on the "free list". _node__free_nonreusable_memory(pCtx, pTree->pNextResult); pTree->pNextResult->displayChildren.p[0] = pTree->pFreeList; pTree->pNextResult->displayChildren.count = 1; pTree->pFreeList = pTree->pNextResult; // Move back up up in the tree. pTree->pNextResult = pTree->pNextResult->pDisplayParent; if(pTree->pNextResult!=NULL) { // The node we just freed... Remove it from its display parent too. --pTree->pNextResult->displayChildren.count; // All children but the leftmost one are indented by 1 from the parent. if(pTree->pNextResult->displayChildren.count>0) --pTree->indentLevel; } } if(pTree->pNextResult->displayChildren.count>0) { SG_uint32 i = pTree->pNextResult->displayChildren.count-1; pTree->pNextResult = pTree->pNextResult->displayChildren.p[i]; if(i>=1) ++pTree->indentLevel; } else { pTree->pNextResult = NULL; } // If we advanced past root... if(pTree->pNextResult==NULL || pTree->pNextResult==pTree->pRoot->displayChildren.p[0]) { // Out with the old root, in with the new... _node__free_nonreusable_memory(pCtx, pTree->pRoot); pTree->pRoot->displayChildren.p[0] = pTree->pFreeList; pTree->pRoot->displayChildren.count = 1; pTree->pFreeList = pTree->pRoot; pTree->pRoot = pTree->pNextResult; if(pTree->pRoot!=NULL) pTree->pRoot->pDisplayParent = NULL; } return; fail: SG_VARRAY_NULLFREE(pCtx, pTmp); }
void SG_sync_remote__get_repo_info( SG_context* pCtx, SG_repo* pRepo, SG_bool bIncludeBranches, SG_bool b_include_areas, SG_vhash** ppvh) { SG_vhash* pvh = NULL; char* pszRepoId = NULL; char* pszAdminId = NULL; char* pszHashMethod = NULL; SG_uint32 count_dagnums = 0; SG_uint64* paDagNums = NULL; SG_uint32 i = 0; SG_vhash* pvh_dags = NULL; SG_vhash* pvh_areas = NULL; SG_vhash* pvhBranchPile = NULL; SG_bool bHasBranchDag = SG_FALSE; SG_NULLARGCHECK_RETURN(pRepo); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvh) ); /* Protocol version */ SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__PROTOCOL_VERSION, 1) ); /* Basic repository info */ SG_ERR_CHECK( SG_repo__get_repo_id(pCtx, pRepo, &pszRepoId) ); SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &pszAdminId) ); SG_ERR_CHECK( SG_repo__get_hash_method(pCtx, pRepo, &pszHashMethod) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__REPO_ID, pszRepoId) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__ADMIN_ID, pszAdminId) ); SG_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvh, SG_SYNC_REPO_INFO_KEY__HASH_METHOD, pszHashMethod) ); /* All DAGs in the repository */ SG_ERR_CHECK( SG_repo__list_dags(pCtx, pRepo, &count_dagnums, &paDagNums) ); SG_ERR_CHECK( SG_vhash__addnew__vhash(pCtx, pvh, "dags", &pvh_dags) ); for (i=0; i<count_dagnums; i++) { char buf_dagnum[SG_DAGNUM__BUF_MAX__HEX]; SG_ERR_CHECK_RETURN( SG_dagnum__to_sz__hex(pCtx, paDagNums[i], buf_dagnum, sizeof(buf_dagnum)) ); SG_ERR_CHECK( SG_vhash__add__null(pCtx, pvh_dags, buf_dagnum) ); /* Asking for a DAG for the first time in a repo will create that DAG. * When pushing into an empty repo, we don't want this initial query to create * empty new DAGs, so we make sure they exist before we query them. */ if (paDagNums[i] == SG_DAGNUM__VC_BRANCHES) bHasBranchDag = SG_TRUE; } // TODO the following code is a problem, because it requires that this repo // instance have indexes, and we would prefer to preserve the ability of // an index-free instance to support push, pull, and clone. /* All areas in the repository */ if (b_include_areas) { SG_ERR_CHECK( SG_area__list(pCtx, pRepo, &pvh_areas) ); if (pvh_areas) { SG_ERR_CHECK( SG_vhash__add__vhash(pCtx, pvh, "areas", &pvh_areas) ); } } /* Branches */ if (bIncludeBranches && bHasBranchDag) { SG_ERR_CHECK( SG_vc_branches__cleanup(pCtx, pRepo, &pvhBranchPile) ); if (pvhBranchPile) { SG_bool bHasBranches; SG_ERR_CHECK( SG_vhash__has(pCtx, pvhBranchPile, "branches", &bHasBranches) ); if (bHasBranches) SG_ERR_CHECK( SG_vhash__add__vhash(pCtx, pvh, "branches", &pvhBranchPile) ); } } *ppvh = pvh; pvh = NULL; /* fall through */ fail: SG_NULLFREE(pCtx, paDagNums); SG_VHASH_NULLFREE(pCtx, pvh); SG_NULLFREE(pCtx, pszRepoId); SG_NULLFREE(pCtx, pszAdminId); SG_NULLFREE(pCtx, pszHashMethod); SG_VHASH_NULLFREE(pCtx, pvh_areas); SG_VHASH_NULLFREE(pCtx, pvhBranchPile); }