void u0038_test_wdmapping(SG_context * pCtx) { SG_vhash* pvh = NULL; SG_closet_descriptor_handle* ph = NULL; SG_pathname* pPath = NULL; SG_pathname* pMappedPath = NULL; SG_string* pstrRepoDescriptorName = NULL; char* pszidGid = NULL; char buf_tid[SG_TID_MAX_BUFFER_LENGTH]; VERIFY_ERR_CHECK_DISCARD( SG_tid__generate2__suffix(pCtx, buf_tid, sizeof(buf_tid), 32, "u0038") ); VERIFY_ERR_CHECK_DISCARD( SG_PATHNAME__ALLOC__SZ(pCtx, &pPath, buf_tid) ); VERIFY_ERR_CHECK_DISCARD( SG_fsobj__mkdir__pathname(pCtx, pPath) ); SG_ERR_IGNORE( SG_closet__descriptors__remove(pCtx, "r1") ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add_begin(pCtx, "r1", NULL, NULL, NULL, NULL, &pvh, &ph) ); VERIFY_ERR_CHECK_DISCARD( SG_closet__descriptors__add_commit(pCtx, &ph, pvh, SG_REPO_STATUS__NORMAL) ); SG_VHASH_NULLFREE(pCtx, 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); }
void SG_workingdir__verify_drawer_exists( SG_context* pCtx, const SG_pathname* pPathWorkingDirectoryTop, SG_pathname** ppResult) { SG_pathname* pDrawerPath = NULL; SG_fsobj_type type = SG_FSOBJ_TYPE__UNSPECIFIED; SG_fsobj_perms perms; SG_bool bExists = SG_FALSE; SG_ERR_CHECK( SG_workingdir__get_drawer_path(pCtx, pPathWorkingDirectoryTop, &pDrawerPath) ); SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pDrawerPath, &bExists, &type, &perms) ); if (!bExists) { SG_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pDrawerPath) ); } else { if (SG_FSOBJ_TYPE__DIRECTORY != type) { SG_ERR_THROW(SG_ERR_NOT_A_DIRECTORY); } } *ppResult = pDrawerPath; return; fail: return; }
/** * Return a pathname set to the location of the "tmp" * directory for this working directory. * * We create something like: * * <root>/.sgdrawer/tmp/ * * Note that the main "tmp" directory is long-lived and * may be used by multiple tasks at the same time. So * for significant tasks, create a private sub-directory * within it. * */ void sg_wc_db__path__get_temp_dir(SG_context * pCtx, const sg_wc_db * pDb, SG_pathname ** ppPathTempDir) { SG_pathname * pPath = NULL; SG_ERR_CHECK( SG_workingdir__get_drawer_path(pCtx, pDb->pPathWorkingDirectoryTop, &pPath) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pPath, "tmp") ); SG_ERR_CHECK( SG_pathname__add_final_slash(pCtx, pPath) ); // the "tmp" dir could get deleted by routine housekeeping, // so re-create it if someone even thinks about using temp-based // pathnames. i'm going to skip the usual "if (!exists) mkdir" // stuff and just try to create it and ignore the error. SG_fsobj__mkdir__pathname(pCtx, pPath); if (SG_CONTEXT__HAS_ERR(pCtx)) { if (!SG_context__err_equals(pCtx, SG_ERR_DIR_ALREADY_EXISTS)) SG_ERR_RETHROW; SG_context__err_reset(pCtx); } *ppPathTempDir = pPath; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPath); }
void u0051_hidlookup_test__1(SG_context * pCtx, SG_pathname* pPathTopDir) { char bufName[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathWorkingDir = NULL; SG_pathname* pPathFile = NULL; SG_dagnode* pdn = NULL; const char* psz_hid_cs = NULL; SG_repo* pRepo = NULL; char buf_partial[256]; char* psz_result = NULL; SG_audit q; VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, bufName, sizeof(bufName), 32) ); /* create the working dir */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathWorkingDir, pPathTopDir, bufName) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathWorkingDir) ); /* add stuff */ VERIFY_ERR_CHECK( u0051_hidlookup__create_file__numbers(pCtx, pPathWorkingDir, "aaa", 20) ); /* create the repo */ VERIFY_ERR_CHECK( _ut_pt__new_repo(pCtx, bufName, pPathWorkingDir) ); VERIFY_ERR_CHECK( _ut_pt__addremove(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( u0051_hidlookup__commit_all(pCtx, pPathWorkingDir, &pdn) ); VERIFY_ERR_CHECK( SG_dagnode__get_id_ref(pCtx, pdn, &psz_hid_cs) ); VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, bufName, &pRepo) ); VERIFY_ERR_CHECK( SG_audit__init(pCtx, &q, pRepo, SG_AUDIT__WHEN__NOW, SG_AUDIT__WHO__FROM_SETTINGS) ); VERIFY_ERR_CHECK( SG_vc_tags__add(pCtx, pRepo, psz_hid_cs, "remember", &q) ); VERIFY_ERR_CHECK( SG_strcpy(pCtx, buf_partial, sizeof(buf_partial), psz_hid_cs) ); buf_partial[10] = 0; VERIFY_ERR_CHECK( SG_repo__hidlookup__dagnode(pCtx, pRepo, SG_DAGNUM__VERSION_CONTROL, buf_partial, &psz_result) ); VERIFY_COND("found", (0 == strcmp(psz_result, psz_hid_cs))); SG_NULLFREE(pCtx, psz_result); VERIFY_ERR_CHECK( SG_repo__hidlookup__blob(pCtx, pRepo, buf_partial, &psz_result) ); VERIFY_COND("found", (0 == strcmp(psz_result, psz_hid_cs))); SG_NULLFREE(pCtx, psz_result); VERIFY_ERR_CHECK( SG_vc_tags__lookup__tag(pCtx, pRepo, "remember", &psz_result) ); VERIFY_COND("found", (0 == strcmp(psz_result, psz_hid_cs))); SG_NULLFREE(pCtx, psz_result); fail: SG_NULLFREE(pCtx, psz_result); SG_REPO_NULLFREE(pCtx, pRepo); SG_DAGNODE_NULLFREE(pCtx, pdn); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_PATHNAME_NULLFREE(pCtx, pPathFile); }
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); }
int u0050_logstuff_test__1(SG_context * pCtx, SG_pathname* pPathTopDir) { char bufName[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathWorkingDir = NULL; SG_pathname* pPathFile = NULL; SG_vhash* pvh = NULL; SG_dagnode* pdn = NULL; const char* psz_hid_cs = NULL; SG_repo* pRepo = NULL; SG_uint32 count; SG_rbtree* prb = NULL; SG_varray* pva = NULL; SG_rbtree* prb_reversed = NULL; const char* psz_val = NULL; SG_audit q; VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, bufName, sizeof(bufName), 32) ); /* create the working dir */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathWorkingDir, pPathTopDir, bufName) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathWorkingDir) ); /* add stuff */ VERIFY_ERR_CHECK( u0050_logstuff__create_file__numbers(pCtx, pPathWorkingDir, "aaa", 20) ); /* create the repo */ VERIFY_ERR_CHECK( _ut_pt__new_repo(pCtx, bufName, pPathWorkingDir) ); VERIFY_ERR_CHECK( _ut_pt__addremove(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( u0050_logstuff__commit_all(pCtx, pPathWorkingDir, &pdn) ); VERIFY_ERR_CHECK( SG_dagnode__get_id_ref(pCtx, pdn, &psz_hid_cs) ); SG_ERR_CHECK( SG_repo__open_repo_instance(pCtx, bufName, &pRepo) ); #define MY_COMMENT "The name of this new file sucks! What kind of a name is 'aaa'?" VERIFY_ERR_CHECK( SG_audit__init(pCtx, &q, pRepo, SG_AUDIT__WHEN__NOW, SG_AUDIT__WHO__FROM_SETTINGS) ); VERIFY_ERR_CHECK( SG_vc_comments__add(pCtx, pRepo, psz_hid_cs, MY_COMMENT, &q) ); VERIFY_ERR_CHECK( SG_vc_stamps__add(pCtx, pRepo, psz_hid_cs, "crap", &q) ); VERIFY_ERR_CHECK( SG_vc_tags__add(pCtx, pRepo, psz_hid_cs, "tcrap", &q) ); VERIFY_ERR_CHECK( SG_vc_comments__lookup(pCtx, pRepo, psz_hid_cs, &pva) ); VERIFY_ERR_CHECK( SG_varray__count(pCtx, pva, &count) ); VERIFY_COND("count", (1 == count)); VERIFY_ERR_CHECK( SG_varray__get__vhash(pCtx, pva, 0, &pvh) ); VERIFY_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh, "text", &psz_val) ); VERIFY_COND("match", (0 == strcmp(psz_val, MY_COMMENT)) ); SG_VARRAY_NULLFREE(pCtx, pva); VERIFY_ERR_CHECK( SG_vc_stamps__lookup(pCtx, pRepo, psz_hid_cs, &pva) ); VERIFY_ERR_CHECK( SG_varray__count(pCtx, pva, &count) ); VERIFY_COND("count", (1 == count)); VERIFY_ERR_CHECK( SG_varray__get__vhash(pCtx, pva, 0, &pvh) ); VERIFY_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh, "stamp", &psz_val) ); VERIFY_COND("match", (0 == strcmp(psz_val, "crap")) ); SG_VARRAY_NULLFREE(pCtx, pva); VERIFY_ERR_CHECK( SG_vc_tags__lookup(pCtx, pRepo, psz_hid_cs, &pva) ); VERIFY_ERR_CHECK( SG_varray__count(pCtx, pva, &count) ); VERIFY_COND("count", (1 == count)); VERIFY_ERR_CHECK( SG_varray__get__vhash(pCtx, pva, 0, &pvh) ); VERIFY_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh, "tag", &psz_val) ); VERIFY_COND("match", (0 == strcmp(psz_val, "tcrap")) ); SG_VARRAY_NULLFREE(pCtx, pva); VERIFY_ERR_CHECK( SG_vc_tags__list(pCtx, pRepo, &prb) ); VERIFY_ERR_CHECK( SG_rbtree__count(pCtx, prb, &count) ); VERIFY_COND("count", (1 == count)); VERIFY_ERR_CHECK( SG_vc_tags__build_reverse_lookup(pCtx, prb, &prb_reversed) ); VERIFY_ERR_CHECK( SG_rbtree__count(pCtx, prb_reversed, &count) ); VERIFY_COND("count", (1 == count)); { const char* psz_my_key = NULL; const char* psz_my_val = NULL; SG_bool b; VERIFY_ERR_CHECK( SG_rbtree__iterator__first(pCtx, NULL, prb_reversed, &b, &psz_my_key, (void**) &psz_my_val) ); VERIFY_COND("ok", (0 == strcmp(psz_my_val, "tcrap")) ); VERIFY_COND("ok", (0 == strcmp(psz_my_key, psz_hid_cs)) ); } SG_RBTREE_NULLFREE(pCtx, prb_reversed); SG_RBTREE_NULLFREE(pCtx, prb); VERIFY_ERR_CHECK( SG_vc_tags__add(pCtx, pRepo, psz_hid_cs, "whatever", &q) ); VERIFY_ERR_CHECK( SG_vc_tags__lookup(pCtx, pRepo, psz_hid_cs, &pva) ); VERIFY_ERR_CHECK( SG_varray__count(pCtx, pva, &count) ); VERIFY_COND("count", (2 == count)); SG_VARRAY_NULLFREE(pCtx, pva); VERIFY_ERR_CHECK( SG_vc_tags__list(pCtx, pRepo, &prb) ); VERIFY_ERR_CHECK( SG_rbtree__count(pCtx, prb, &count) ); VERIFY_COND("count", (2 == count)); VERIFY_ERR_CHECK( SG_vc_tags__build_reverse_lookup(pCtx, prb, &prb_reversed) ); VERIFY_ERR_CHECK( SG_rbtree__count(pCtx, prb_reversed, &count) ); VERIFY_COND("count", (1 == count)); { const char* psz_my_key = NULL; const char* psz_my_val = NULL; SG_bool b; VERIFY_ERR_CHECK( SG_rbtree__iterator__first(pCtx, NULL, prb_reversed, &b, &psz_my_key, (void**) &psz_my_val) ); VERIFY_COND("ok", (0 == strcmp(psz_my_key, psz_hid_cs)) ); /* we don't know whether psz_my_val is tcrap or whatever. */ // VERIFY_COND("ok", (0 == strcmp(psz_my_val, "tcrap")) ); } SG_RBTREE_NULLFREE(pCtx, prb_reversed); SG_RBTREE_NULLFREE(pCtx, prb); { const char* psz_remove = "whatever"; VERIFY_ERR_CHECK( SG_vc_tags__remove(pCtx, pRepo, &q, 1, &psz_remove) ); /* Note that by removing whatever, we are bringing the tags list back * to a state where it has been before (just tcrap). This changeset in * the tags table will have its own csid, because the parentage is * different, but it's root idtrie HID will be the same as a previous * node. */ } VERIFY_ERR_CHECK( SG_vc_tags__lookup(pCtx, pRepo, psz_hid_cs, &pva) ); VERIFY_ERR_CHECK( SG_varray__count(pCtx, pva, &count) ); VERIFY_COND("count", (1 == count)); SG_VARRAY_NULLFREE(pCtx, pva); VERIFY_ERR_CHECK( SG_vc_tags__list(pCtx, pRepo, &prb) ); VERIFY_ERR_CHECK( SG_rbtree__count(pCtx, prb, &count) ); VERIFY_COND("count", (1 == count)); SG_RBTREE_NULLFREE(pCtx, prb); SG_REPO_NULLFREE(pCtx, pRepo); SG_DAGNODE_NULLFREE(pCtx, pdn); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_PATHNAME_NULLFREE(pCtx, pPathFile); return 1; fail: SG_VHASH_NULLFREE(pCtx, pvh); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_PATHNAME_NULLFREE(pCtx, pPathFile); return 0; }
void sg_sync_client__http__push_begin( SG_context* pCtx, SG_sync_client * pSyncClient, SG_pathname** pFragballDirPathname, SG_sync_client_push_handle** ppPush) { char* pszUrl = NULL; sg_sync_client_http_push_handle* pPush = NULL; SG_vhash* pvhResponse = NULL; SG_pathname* pPathUserTemp = NULL; SG_pathname* pPathFragballDir = NULL; char bufTid[SG_TID_MAX_BUFFER_LENGTH]; SG_string* pstr = NULL; SG_NULLARGCHECK_RETURN(pSyncClient); SG_NULLARGCHECK_RETURN(pFragballDirPathname); SG_NULLARGCHECK_RETURN(ppPush); // Get the URL we're going to post to SG_ERR_CHECK( _get_sync_url(pCtx, pSyncClient->psz_remote_repo_spec, SYNC_URL_SUFFIX JSON_URL_SUFFIX, NULL, NULL, &pszUrl) ); SG_ERR_CHECK( do_url(pCtx, pszUrl, "POST", NULL, pSyncClient->psz_username, pSyncClient->psz_password, &pstr, NULL, SG_TRUE) ); SG_ERR_CHECK( SG_vhash__alloc__from_json__sz(pCtx, &pvhResponse, SG_string__sz(pstr)) ); SG_STRING_NULLFREE(pCtx, pstr); // Alloc a push handle. Stuff the push ID we received into it. { const char* pszRef = NULL; SG_ERR_CHECK( SG_alloc(pCtx, 1, sizeof(sg_sync_client_http_push_handle), &pPush) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhResponse, PUSH_ID_KEY, &pszRef) ); SG_ERR_CHECK( SG_strdup(pCtx, pszRef, &pPush->pszPushId) ); } // Create a temporary local directory for stashing fragballs before shipping them over the network. SG_ERR_CHECK( SG_PATHNAME__ALLOC__USER_TEMP_DIRECTORY(pCtx, &pPathUserTemp) ); SG_ERR_CHECK( SG_tid__generate(pCtx, bufTid, SG_TID_MAX_BUFFER_LENGTH) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathFragballDir, pPathUserTemp, bufTid) ); SG_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathFragballDir) ); // Tell caller where to stash fragballs for this push. SG_RETURN_AND_NULL(pPathFragballDir, pFragballDirPathname); // Return the new push handle. *ppPush = (SG_sync_client_push_handle*)pPush; pPush = NULL; /* fall through */ fail: SG_STRING_NULLFREE(pCtx, pstr); if(SG_context__err_equals(pCtx, SG_ERR_SERVER_HTTP_ERROR)) { const char * szInfo = NULL; if(SG_IS_OK(SG_context__err_get_description(pCtx, &szInfo)) && strcmp(szInfo, "405")==0) SG_ERR_RESET_THROW(SG_ERR_SERVER_DOESNT_ACCEPT_PUSHES); } _NULLFREE_PUSH_HANDLE(pCtx, pPush); SG_NULLFREE(pCtx, pszUrl); SG_PATHNAME_NULLFREE(pCtx, pPathUserTemp); SG_PATHNAME_NULLFREE(pCtx, pPathFragballDir); SG_VHASH_NULLFREE(pCtx, pvhResponse); }
/** * This function is used to get a new tree. It must be called with the HID of * the top-level user root directory. Not the super-root. The directory which * corresponds to @. * * Record the file timestamp of each file we fetch in the pvhTimestamps; this * provides the basis for the timestamp check in scan-dir. */ static void sg_workingdir__do_get_dir__top(SG_context* pCtx, SG_repo* pRepo, const SG_pathname* pPathLocal, const char* pszidHidTreeNode, SG_vhash * pvhTimestamps) { SG_pathname* pPathSub = NULL; SG_treenode* pTreenode = NULL; SG_string* pstrLink = NULL; SG_byte* pBytes = NULL; SG_vhash* pvhAttributes = NULL; SG_int64 iAttributeBits = 0; const SG_treenode_entry* pEntry = NULL; const char* pszidHidContent = NULL; #ifdef SG_BUILD_FLAG_FEATURE_XATTR const char* pszidHidXattrs = NULL; #endif SG_bool bExists = SG_FALSE; /* Load the treenode. It should have exactly one entry, a subdirectory, * named @ */ SG_ERR_CHECK( SG_treenode__load_from_repo(pCtx, pRepo, pszidHidTreeNode, &pTreenode) ); SG_ERR_CHECK( SG_treenode__get_nth_treenode_entry__ref(pCtx, pTreenode, 0, NULL, &pEntry) ); SG_ERR_CHECK( SG_treenode_entry__get_hid_blob(pCtx, pEntry, &pszidHidContent) ); #ifdef DEBUG { SG_uint32 count; SG_treenode_entry_type type; const char* pszName = NULL; SG_ERR_CHECK( SG_treenode__count(pCtx, pTreenode, &count) ); SG_ASSERT(1 == count); SG_ERR_CHECK( SG_treenode_entry__get_entry_type(pCtx, pEntry, &type) ); SG_ASSERT (SG_TREENODEENTRY_TYPE_DIRECTORY == type); SG_ERR_CHECK( SG_treenode_entry__get_entry_name(pCtx, pEntry, &pszName) ); SG_ASSERT(0 == strcmp(pszName, "@")); } #endif /* create the directory and then dive into it */ SG_ERR_CHECK( SG_PATHNAME__ALLOC__COPY(pCtx, &pPathSub, pPathLocal) ); SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pPathSub, &bExists, NULL, NULL) ); if (!bExists) SG_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathSub) ); SG_ERR_CHECK( _sg_workingdir__get_dir(pCtx, pRepo, pPathSub, pszidHidContent, pvhTimestamps) ); #ifdef SG_BUILD_FLAG_FEATURE_XATTR /* fix up the xattrs on that directory */ SG_ERR_CHECK( SG_treenode_entry__get_hid_xattrs(pCtx, pEntry, &pszidHidXattrs) ); if (pszidHidXattrs) { SG_ERR_CHECK( SG_repo__fetch_vhash(pCtx, pRepo, pszidHidXattrs, &pvhAttributes) ); SG_ERR_CHECK( SG_attributes__xattrs__apply(pCtx, pPathSub, pvhAttributes, pRepo) ); SG_VHASH_NULLFREE(pCtx, pvhAttributes); } #endif /* and the attrbits too */ SG_ERR_CHECK( SG_treenode_entry__get_attribute_bits(pCtx, pEntry, &iAttributeBits) ); SG_ERR_CHECK( SG_attributes__bits__apply(pCtx, pPathSub, iAttributeBits) ); SG_PATHNAME_NULLFREE(pCtx, pPathSub); SG_TREENODE_NULLFREE(pCtx, pTreenode); return; fail: /* TODO free stuff */ SG_VHASH_NULLFREE(pCtx, pvhAttributes); SG_NULLFREE(pCtx, pBytes); SG_STRING_NULLFREE(pCtx, pstrLink); }
static void _sg_workingdir__get_entry2(SG_context * pCtx, SG_repo * pRepo, const SG_pathname * pPathSub, const char * pszGid, SG_treenode_entry_type type, const char * pszidHidContent, const char * pszidHidXattrs, SG_int64 iAttributeBits, SG_vhash * pvhTimestamps) { SG_file* pFile = NULL; SG_string* pstrLink = NULL; SG_byte* pBytes = NULL; SG_vhash * pvhGid = NULL; if (SG_TREENODEENTRY_TYPE_DIRECTORY == type) { /* create the directory and then recurse into it */ SG_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathSub) ); SG_ERR_CHECK( _sg_workingdir__get_dir(pCtx, pRepo, pPathSub, pszidHidContent, pvhTimestamps) ); } else if (SG_TREENODEENTRY_TYPE_REGULAR_FILE == type) { SG_ERR_CHECK( SG_file__open__pathname(pCtx, pPathSub, SG_FILE_RDWR | SG_FILE_CREATE_NEW, SG_FSOBJ_PERMS__MASK, &pFile) ); SG_ERR_CHECK( SG_repo__fetch_blob_into_file(pCtx, pRepo, pszidHidContent, pFile, NULL) ); SG_ERR_CHECK( SG_file__close(pCtx, &pFile) ); } else if (SG_TREENODEENTRY_TYPE_SYMLINK == type) { SG_uint64 iLenBytes = 0; SG_ERR_CHECK( SG_repo__fetch_blob_into_memory(pCtx, pRepo, pszidHidContent, &pBytes, &iLenBytes) ); SG_ERR_CHECK( SG_STRING__ALLOC__BUF_LEN(pCtx, &pstrLink, pBytes, (SG_uint32) iLenBytes) ); SG_ERR_CHECK( SG_fsobj__symlink(pCtx, pstrLink, pPathSub) ); SG_NULLFREE(pCtx, pBytes); SG_STRING_NULLFREE(pCtx, pstrLink); } else { SG_ERR_THROW(SG_ERR_NOTIMPLEMENTED); } if (pszidHidXattrs) { #ifdef SG_BUILD_FLAG_FEATURE_XATTR SG_ERR_CHECK( _sg_workingdir__set_xattrs(pCtx, pRepo, pPathSub, pszidHidXattrs) ); #else // TODO do we need to stuff something into the pendingtree to remind us // TODO that the entry originally had an XAttr and we just didn't restore // TODO it when we populated the WD on this Windows system? #endif } SG_ERR_CHECK( SG_attributes__bits__apply(pCtx, pPathSub, iAttributeBits) ); if (pvhTimestamps && (SG_TREENODEENTRY_TYPE_REGULAR_FILE == type)) { SG_fsobj_stat stat; SG_int64 iTimeNow; SG_ERR_CHECK( SG_fsobj__stat__pathname(pCtx, pPathSub, &stat) ); SG_ERR_CHECK( SG_time__get_milliseconds_since_1970_utc(pCtx, &iTimeNow) ); SG_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhGid) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pvhGid, "mtime_ms", stat.mtime_ms) ); SG_ERR_CHECK( SG_vhash__add__int64(pCtx, pvhGid, "clock_ms", iTimeNow) ); SG_ERR_CHECK( SG_vhash__add__vhash(pCtx, pvhTimestamps, pszGid, &pvhGid) ); // this steals our vhash } fail: SG_VHASH_NULLFREE(pCtx, pvhGid); }
void MyFn(test__simple)(SG_context* pCtx) { char bufTopDir[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathTopDir = NULL; char buf_client_repo_name[SG_TID_MAX_BUFFER_LENGTH]; char buf_server_repo_name[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathWorkingDir = NULL; SG_vhash* pvh = NULL; SG_repo* pClientRepo = NULL; SG_client* pClient = NULL; SG_repo* pServerRepo = NULL; SG_bool bMatch = SG_FALSE; SG_varray* pvaZingMergeLog = NULL; SG_varray* pvaZingMergeErr = NULL; VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, bufTopDir, sizeof(bufTopDir), 32) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx,&pPathTopDir,bufTopDir) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx,pPathTopDir) ); VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, buf_client_repo_name, sizeof(buf_client_repo_name), 32) ); VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, buf_server_repo_name, sizeof(buf_server_repo_name), 32) ); INFOP("test__simple", ("client repo: %s", buf_client_repo_name)); INFOP("test__simple", ("server repo: %s", buf_server_repo_name)); /* create the repo */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathWorkingDir, pPathTopDir, buf_server_repo_name) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( _ut_pt__new_repo2(pCtx, buf_server_repo_name, pPathWorkingDir, NULL) ); /* open that repo */ VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, buf_server_repo_name, &pServerRepo) ); /* create an empty clone to pull into */ VERIFY_ERR_CHECK( SG_repo__create_empty_clone(pCtx, buf_server_repo_name, buf_client_repo_name) ); VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, buf_client_repo_name, &pClientRepo) ); /* add stuff to server repo */ VERIFY_ERR_CHECK( MyFn(create_file__numbers)(pCtx, pPathWorkingDir, "aaa", 10) ); VERIFY_ERR_CHECK( _ut_pt__addremove(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( MyFn(commit_all)(pCtx, pPathWorkingDir, NULL) ); VERIFY_ERR_CHECK( MyFn(create_file__numbers)(pCtx, pPathWorkingDir, "bbb", 10) ); VERIFY_ERR_CHECK( _ut_pt__addremove(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( MyFn(commit_all)(pCtx, pPathWorkingDir, NULL) ); /* verify pre-pull repos are different */ VERIFY_ERR_CHECK( SG_sync__compare_repo_dags(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("pre-pull repos differ", !bMatch); /* get a client and pull from server repo to empty client repo */ VERIFY_ERR_CHECK( SG_client__open(pCtx, buf_server_repo_name, NULL_CREDENTIAL, &pClient) ); // TODO Credentials VERIFY_ERR_CHECK( SG_pull__all(pCtx, buf_client_repo_name, pClient, &pvaZingMergeErr, &pvaZingMergeLog) ); VERIFY_COND("", !pvaZingMergeErr); SG_CLIENT_NULLFREE(pCtx, pClient); /* verify post-pull repos are identical */ VERIFY_ERR_CHECK( SG_sync__compare_repo_dags(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-pull repo DAGs differ", bMatch); VERIFY_ERR_CHECK( SG_sync__compare_repo_blobs(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-pull repo blobs differ", bMatch); VERIFY_ERR_CHECK( SG_repo__check_integrity(pCtx, pClientRepo, SG_REPO__CHECK_INTEGRITY__DAG_CONSISTENCY, SG_DAGNUM__VERSION_CONTROL, NULL, NULL) ); /* TODO: verify more stuff? */ /* Fall through to common cleanup */ fail: /* close client */ SG_CLIENT_NULLFREE(pCtx, pClient); /* close both repos */ SG_REPO_NULLFREE(pCtx, pServerRepo); SG_REPO_NULLFREE(pCtx, pClientRepo); SG_PATHNAME_NULLFREE(pCtx, pPathTopDir); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_VHASH_NULLFREE(pCtx, pvh); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_VARRAY_NULLFREE(pCtx, pvaZingMergeLog); SG_VARRAY_NULLFREE(pCtx, pvaZingMergeErr); }
void MyFn(test__wide_dag)(SG_context* pCtx) { char bufTopDir[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathTopDir = NULL; char buf_client_repo_name[SG_TID_MAX_BUFFER_LENGTH]; char buf_server_repo_name[SG_TID_MAX_BUFFER_LENGTH]; SG_pathname* pPathWorkingDir = NULL; SG_vhash* pvh = NULL; SG_repo* pClientRepo = NULL; SG_client* pClient = NULL; char* pszidFirstChangeset = NULL; SG_pathname* pPathCsDir = NULL; SG_uint32 lines; SG_uint32 i, j; SG_repo* pServerRepo = NULL; SG_bool bMatch = SG_FALSE; char buf_filename[7]; SG_varray* pvaZingMergeLog = NULL; SG_varray* pvaZingMergeErr = NULL; VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, bufTopDir, sizeof(bufTopDir), 32) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx,&pPathTopDir,bufTopDir) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx,pPathTopDir) ); VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, buf_client_repo_name, sizeof(buf_client_repo_name), 32) ); VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, buf_server_repo_name, sizeof(buf_server_repo_name), 32) ); INFOP("test__wide_dag", ("client repo: %s", buf_client_repo_name)); INFOP("test__wide_dag", ("server repo: %s", buf_server_repo_name)); /* create the repo */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathWorkingDir, pPathTopDir, buf_server_repo_name) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( _ut_pt__new_repo2(pCtx, buf_server_repo_name, pPathWorkingDir, &pszidFirstChangeset) ); /* open that repo */ VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, buf_server_repo_name, &pServerRepo) ); /* create an empty clone to pull into */ VERIFY_ERR_CHECK( SG_repo__create_empty_clone(pCtx, buf_server_repo_name, buf_client_repo_name) ); VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, buf_client_repo_name, &pClientRepo) ); /* add stuff to server repo */ for (i = 0; i < 20; i++) // number of changesets { VERIFY_ERR_CHECK( _ut_pt__set_baseline(pCtx, pPathWorkingDir, pszidFirstChangeset) ); VERIFY_ERR_CHECK( SG_sprintf(pCtx, buf_filename, sizeof(buf_filename), "%d", i) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathCsDir, pPathWorkingDir, buf_filename) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir__pathname(pCtx, pPathCsDir) ); for (j = 0; j < 1; j++) // number of files added per changeset { VERIFY_ERR_CHECK( SG_sprintf(pCtx, buf_filename, sizeof(buf_filename), "%d", j) ); lines = (int)(2500.0 * (rand() / (RAND_MAX + 1.0))); VERIFY_ERR_CHECK( MyFn(create_file__numbers)(pCtx, pPathCsDir, buf_filename, lines) ); } SG_PATHNAME_NULLFREE(pCtx, pPathCsDir); VERIFY_ERR_CHECK( _ut_pt__addremove(pCtx, pPathWorkingDir) ); VERIFY_ERR_CHECK( MyFn(commit_all)(pCtx, pPathWorkingDir, NULL) ); } /* verify pre-pull repos are different */ VERIFY_ERR_CHECK( SG_sync__compare_repo_dags(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("pre-pull repos differ", !bMatch); /* get a client and pull from server repo to empty client repo */ VERIFY_ERR_CHECK( SG_client__open(pCtx, buf_server_repo_name, NULL_CREDENTIAL, &pClient) ); // TODO Credentials VERIFY_ERR_CHECK( SG_pull__all(pCtx, buf_client_repo_name, pClient, &pvaZingMergeErr, &pvaZingMergeLog) ); VERIFY_COND("", !pvaZingMergeErr); /* verify post-pull repos are identical */ VERIFY_ERR_CHECK( SG_sync__compare_repo_dags(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-pull repo DAGs differ", bMatch); VERIFY_ERR_CHECK( SG_sync__compare_repo_blobs(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-pull repo blobs differ", bMatch); VERIFY_ERR_CHECK( SG_repo__check_integrity(pCtx, pClientRepo, SG_REPO__CHECK_INTEGRITY__DAG_CONSISTENCY, SG_DAGNUM__VERSION_CONTROL, NULL, NULL) ); SG_REPO_NULLFREE(pCtx, pClientRepo); /* Make another copy with clone */ VERIFY_ERR_CHECK( SG_tid__generate2(pCtx, buf_client_repo_name, sizeof(buf_client_repo_name), 32) ); SG_ERR_CHECK( SG_repo__create_empty_clone_from_remote(pCtx, pClient, buf_client_repo_name) ); VERIFY_ERR_CHECK( SG_pull__clone(pCtx, buf_client_repo_name, pClient) ); /* verify post-clone repos are identical */ VERIFY_ERR_CHECK( SG_repo__open_repo_instance(pCtx, buf_client_repo_name, &pClientRepo) ); VERIFY_ERR_CHECK( SG_sync__compare_repo_dags(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-clone repo DAGs differ", bMatch); VERIFY_ERR_CHECK( SG_sync__compare_repo_blobs(pCtx, pClientRepo, pServerRepo, &bMatch) ); VERIFY_COND_FAIL("post-clone repo blobs differ", bMatch); VERIFY_ERR_CHECK( SG_repo__check_integrity(pCtx, pClientRepo, SG_REPO__CHECK_INTEGRITY__DAG_CONSISTENCY, SG_DAGNUM__VERSION_CONTROL, NULL, NULL) ); /* TODO: verify more stuff? */ /* Fall through to common cleanup */ fail: /* close client */ SG_CLIENT_NULLFREE(pCtx, pClient); /* close both repos */ SG_REPO_NULLFREE(pCtx, pServerRepo); SG_REPO_NULLFREE(pCtx, pClientRepo); SG_NULLFREE(pCtx, pszidFirstChangeset); SG_PATHNAME_NULLFREE(pCtx, pPathTopDir); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_PATHNAME_NULLFREE(pCtx, pPathCsDir); SG_VHASH_NULLFREE(pCtx, pvh); SG_PATHNAME_NULLFREE(pCtx, pPathWorkingDir); SG_VARRAY_NULLFREE(pCtx, pvaZingMergeLog); SG_VARRAY_NULLFREE(pCtx, pvaZingMergeErr); }