void u0023_vcdiff__test_deltify_run(SG_context * pCtx) { FILE* fp; SG_pathname* pPath_version1 = NULL; SG_pathname* pPath_version2 = NULL; int i; VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version1) ); VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version2) ); fp = fopen(SG_pathname__sz(pPath_version1), "w"); fprintf(fp, "Ah, I should havq known it from thq vqry start This girl will lqavq mq with a brokqn hqart Now listqn pqoplq what I'm tqlling you A-kqqp away from-a Runaround Suq\n"); fclose(fp); fp = fopen(SG_pathname__sz(pPath_version2), "w"); for (i=0; i<500000; i++) { fputc('e', fp); } fclose(fp); VERIFY_ERR_CHECK_DISCARD( u0023_vcdiff__do_test_deltify(pCtx, pPath_version1, pPath_version2) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version1) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version2) ); SG_PATHNAME_NULLFREE(pCtx, pPath_version1); SG_PATHNAME_NULLFREE(pCtx, pPath_version2); }
void u0023_vcdiff__test_deltify(SG_context * pCtx) { FILE* fp; SG_pathname* pPath_version1 = NULL; SG_pathname* pPath_version2 = NULL; int i; VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx,&pPath_version1) ); VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx,&pPath_version2) ); fp = fopen(SG_pathname__sz(pPath_version1), "w"); for (i=0; i<500; i++) { fprintf(fp, "Ah, I should have known it from the very start This girl will leave me with a broken heart Now listen people what I'm telling you A-keep away from-a Runaround Sue\n"); } fclose(fp); fp = fopen(SG_pathname__sz(pPath_version2), "w"); for (i=0; i<100; i++) { fprintf(fp, "He rocks in the tree-top all a day long Hoppin' and a-boppin' and a-singin' the song All the little birds on J-Bird St. Love to hear the robin goin' tweet tweet tweet\n"); } fclose(fp); VERIFY_ERR_CHECK_DISCARD( u0023_vcdiff__do_test_deltify(pCtx, pPath_version1, pPath_version2) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version1) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version2) ); SG_PATHNAME_NULLFREE(pCtx, pPath_version1); SG_PATHNAME_NULLFREE(pCtx, pPath_version2); }
void u0023_vcdiff__test_deltify_small_files(SG_context * pCtx) { FILE* fp; SG_pathname* pPath_version1; SG_pathname* pPath_version2; VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version1) ); VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version2) ); fp = fopen(SG_pathname__sz(pPath_version1), "w"); fprintf(fp, "e"); fclose(fp); fp = fopen(SG_pathname__sz(pPath_version2), "w"); fprintf(fp, "a"); fclose(fp); VERIFY_ERR_CHECK_DISCARD( u0023_vcdiff__do_test_deltify(pCtx, pPath_version1, pPath_version2) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version1) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version2) ); SG_PATHNAME_NULLFREE(pCtx, pPath_version1); SG_PATHNAME_NULLFREE(pCtx, pPath_version2); }
void u0023_vcdiff__test_deltify_from_zerolength(SG_context * pCtx) { FILE* fp; SG_pathname* pPath_version1 = NULL; SG_pathname* pPath_version2 = NULL; int i; VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version1) ); VERIFY_ERR_CHECK_DISCARD( unittest__get_nonexistent_pathname(pCtx, &pPath_version2) ); fp = fopen(SG_pathname__sz(pPath_version1), "w"); fclose(fp); fp = fopen(SG_pathname__sz(pPath_version2), "w"); for (i=0; i<500000; i++) { fputc(i % 256, fp); } fclose(fp); VERIFY_ERR_CHECK_DISCARD( u0023_vcdiff__do_test_deltify(pCtx, pPath_version1, pPath_version2) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version1) ); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx, pPath_version2) ); SG_PATHNAME_NULLFREE(pCtx, pPath_version1); SG_PATHNAME_NULLFREE(pCtx, pPath_version2); }
STDMETHODIMP CVeracityOverlay_Ignored::IsMemberOf(LPCWSTR pwszPath, DWORD dwAttrib) { pwszPath; dwAttrib; HRESULT returnVal = S_FALSE; //return returnVal; SG_context* pCtx = GetAContext(); SG_pathname * pPathCwd = NULL; SG_pathname * pPathTop = NULL; if (InAWorkingFolder(pCtx, pwszPath, &pPathCwd, &pPathTop) ) { SG_wc_status_flags status = GetStatus(pCtx, SG_pathname__sz(pPathCwd), SG_pathname__sz(pPathTop), NULL); if (StatusHas(status, SG_WC_STATUS_FLAGS__U__IGNORED) || StatusHas(status, SG_WC_STATUS_FLAGS__R__RESERVED) ) returnVal = S_OK; else returnVal = S_FALSE; } else returnVal = S_FALSE; SG_PATHNAME_NULLFREE(pCtx, pPathCwd); SG_PATHNAME_NULLFREE(pCtx, pPathTop); SG_CONTEXT_NULLFREE(pCtx); return returnVal; }
void _sg_mrg__copy_wc_to_temp_file(SG_context * pCtx, SG_mrg * pMrg, SG_mrg_cset_entry * pMrgCSetEntry, const SG_pathname * pPathTempFile) { sg_wc_liveview_item * pLVI; SG_string * pStringRepoPath = NULL; SG_pathname * pPathInWC = NULL; SG_bool bExists; SG_bool bKnown; SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx,pPathTempFile,&bExists,NULL,NULL) ); if (bExists) { #if TRACE_WC_MERGE SG_ERR_IGNORE( SG_console(pCtx,SG_CS_STDERR, "Skipping copy of WC version to [%s]\n", SG_pathname__sz(pPathTempFile)) ); #endif return; } // Find the absolute path of the WD version of the file. SG_ERR_CHECK( sg_wc_tx__liveview__fetch_random_item(pCtx, pMrg->pWcTx, pMrgCSetEntry->uiAliasGid, &bKnown, &pLVI) ); SG_ASSERT_RELEASE_FAIL( (bKnown) ); SG_ERR_CHECK( sg_wc_tx__liveview__compute_live_repo_path(pCtx, pMrg->pWcTx, pLVI, &pStringRepoPath) ); SG_ERR_CHECK( sg_wc_db__path__repopath_to_absolute(pCtx, pMrg->pWcTx->pDb, pStringRepoPath, &pPathInWC) ); #if TRACE_WC_MERGE SG_ERR_IGNORE( SG_console(pCtx,SG_CS_STDERR, "Copying WC version [%s] to [%s]\n", SG_string__sz(pStringRepoPath), SG_pathname__sz(pPathTempFile)) ); #endif // Ideally, when we create this TEMP file it should be read-only. // Afterall, it does represent a historical version of the file and // it should only be used as INPUT to whatever merge tool the user // has configured. So it should be read-only. This might allow // a GUI merge tool to show locks/whatever and/or prevent accidental // editing of these files. // // However, this can cause an "Access is Denied" error on Windows // when we get ready to delete the contents of the TEMP directory. // We'll deal with that there rather than here. SG_ERR_CHECK( SG_fsobj__copy_file(pCtx, pPathInWC, pPathTempFile, 0400) ); fail: SG_STRING_NULLFREE(pCtx, pStringRepoPath); SG_PATHNAME_NULLFREE(pCtx, pPathInWC); }
void sg_treediff_cache::GetStatusForPath(SG_context * pCtx, SG_bool bIsRetry, const SG_pathname * pPathName, SG_wc_status_flags * pStatusFlags, SG_bool * pbDirChanged) { wxCriticalSectionLocker lock(m_wc_transaction_lock); SG_wc_status_flags statusFlags = SG_WC_STATUS_FLAGS__U__FOUND; SG_string * psgstr_statusFlagsDetails = NULL; if (m_pwc_tx == NULL) { //Start a read-only transaction. SG_ERR_CHECK( SG_WC_TX__ALLOC__BEGIN(pCtx, &m_pwc_tx, ((pPathName)), SG_TRUE) ); } SG_ERR_CHECK( SG_wc_tx__get_item_status_flags(pCtx, m_pwc_tx, SG_pathname__sz(pPathName), SG_FALSE, SG_FALSE, &statusFlags, NULL) ); if (pbDirChanged != NULL && (statusFlags & SG_WC_STATUS_FLAGS__T__DIRECTORY)) { //It's a directory, so we need to check to see if there are modifications under it. SG_wc_status_flags dirStatusFlags = SG_WC_STATUS_FLAGS__U__FOUND; SG_ERR_CHECK( SG_wc_tx__get_item_dirstatus_flags(pCtx, m_pwc_tx, SG_pathname__sz(pPathName), &dirStatusFlags, NULL, pbDirChanged) ); } #if DEBUG SG_ERR_CHECK( SG_wc_debug__status__dump_flags(pCtx, statusFlags, "status flags", &psgstr_statusFlagsDetails) ); SG_ERR_CHECK( SG_log__report_verbose(pCtx, "%s", SG_string__sz(psgstr_statusFlagsDetails)) ); #endif //Don't recurse if this is our second try. if ((bIsRetry == SG_FALSE) && ((statusFlags & SG_WC_STATUS_FLAGS__T__BOGUS) == SG_WC_STATUS_FLAGS__T__BOGUS) ) { //This is a item that is new in the directory since we started //our transaction. Close the transaction, and start a new one. SG_ERR_CHECK( SG_log__report_verbose(pCtx, "Got a bogus status. Restarting transaction") ); clearCache(pCtx); GetStatusForPath(pCtx, SG_TRUE, pPathName, &statusFlags, pbDirChanged); } SG_ERR_CHECK( SG_time__get_milliseconds_since_1970_utc(pCtx, &m_timeLastRequest) ); *pStatusFlags = statusFlags; fail: SG_STRING_NULLFREE(pCtx, psgstr_statusFlagsDetails); //Log and reset any errors on the context. //Any error condition should report the status as //Found and still send a message back to the client. if (SG_context__has_err(pCtx) == SG_TRUE) { if (!SG_context__err_equals(pCtx, SG_ERR_WC_DB_BUSY)) { SG_log__report_error__current_error(pCtx); } SG_context__err_reset(pCtx); } }
/** * Create a per-tx temp-dir if we don't already have one. * */ void sg_wc_tx__create_session_temp_dir(SG_context * pCtx, SG_wc_tx * pWcTx) { char bufTidSession[SG_TID_MAX_BUFFER_LENGTH]; SG_uint32 nrDigits = 10; if (pWcTx->pPathSessionTempDir) return; // pick a space in /tmp for exporting temporary copies of the files // so that internal and/or external tools can compare them. // // TODO 2012/05/02 Investigate the use of SG_workingdir__get_temp_path() (which // TODO creates things in .sgdrawer rather than /tmp). // TODO (see also sg_mrg__private_file_mrg.h) // TODO See also sg_vv2__diff__create_session_temp_dir(). SG_ERR_CHECK( SG_PATHNAME__ALLOC__USER_TEMP_DIRECTORY(pCtx, &pWcTx->pPathSessionTempDir) ); SG_ERR_CHECK( SG_tid__generate2(pCtx, bufTidSession, sizeof(bufTidSession), nrDigits) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pWcTx->pPathSessionTempDir, bufTidSession) ); SG_ERR_TRY( SG_fsobj__mkdir_recursive__pathname(pCtx, pWcTx->pPathSessionTempDir) ); SG_ERR_CATCH_IGNORE( SG_ERR_DIR_ALREADY_EXISTS ); SG_ERR_CATCH_END; #if 0 && defined(DEBUG) SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "CreateSessionTempDir: %s\n", SG_pathname__sz(pWcTx->pPathSessionTempDir)) ); #endif fail: return; }
/** * Convert relative path to absolute, but make * sure that normalization doesn't take it outside * of the working directory. * * This is just pathname/string parsing; we DO NOT * confirm that the path exists or could exist. * */ void sg_wc_db__path__relative_to_absolute(SG_context * pCtx, const sg_wc_db * pDb, const SG_string * pStringRelativePath, SG_pathname ** ppPathItem) { SG_pathname * pPathWDT = NULL; SG_pathname * pPath = NULL; SG_uint32 lenWDT; // choke if they give us a repo-path. SG_ARGCHECK_RETURN( (SG_string__sz(pStringRelativePath)[0] != '@'), pStringRelativePath ); // choke if this WC TX isn't cwd-based. SG_ERR_CHECK( _check_if_relative_paths_allowed(pCtx, pDb) ); // clone WDT so that we can force a trailing slash. SG_ERR_CHECK( SG_PATHNAME__ALLOC__COPY(pCtx, &pPathWDT, pDb->pPathWorkingDirectoryTop) ); SG_ERR_CHECK( SG_pathname__add_final_slash(pCtx, pPathWDT) ); lenWDT = SG_pathname__length_in_bytes(pPathWDT); // allocate and normalize a new path with the net // result rather than writing on the clone (so that // we can do the following prefix test safely). SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPath, pPathWDT, SG_string__sz(pStringRelativePath)) ); if (strncmp(SG_pathname__sz(pPath), SG_pathname__sz(pPathWDT), lenWDT) != 0) { SG_ERR_THROW2( SG_ERR_PATH_NOT_IN_WORKING_COPY, (pCtx, "The path '%s' is not inside the working copy rooted at '%s'.", SG_string__sz(pStringRelativePath), SG_pathname__sz(pDb->pPathWorkingDirectoryTop)) ); } SG_PATHNAME_NULLFREE(pCtx, pPathWDT); *ppPathItem = pPath; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPathWDT); SG_PATHNAME_NULLFREE(pCtx, pPath); }
/** * Export the contents of the given file entry (which reflects a specific version) * into a temp file so that an external tool can use it. * * You own the returned pathname and the file on disk. */ void _sg_mrg__export_to_temp_file(SG_context * pCtx, SG_mrg * pMrg, const char * pszHidBlob, const SG_pathname * pPathTempFile) { SG_file * pFile = NULL; SG_bool bExists; SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx,pPathTempFile,&bExists,NULL,NULL) ); if (bExists) { #if TRACE_WC_MERGE SG_ERR_IGNORE( SG_console(pCtx,SG_CS_STDERR, "Skipping export of [blob %s] to [%s]\n",pszHidBlob,SG_pathname__sz(pPathTempFile)) ); #endif } else { #if TRACE_WC_MERGE SG_ERR_IGNORE( SG_console(pCtx,SG_CS_STDERR, "Exporting [blob %s] to [%s]\n",pszHidBlob,SG_pathname__sz(pPathTempFile)) ); #endif // Ideally, when we create this TEMP file it should be read-only. // Afterall, it does represent a historical version of the file and // it should only be used as INPUT to whatever merge tool the user // has configured. So it should be read-only. This might allow // a GUI merge tool to show locks/whatever and/or prevent accidental // editing of these files. // // However, this can cause an "Access is Denied" error on Windows // when we get ready to delete the contents of the TEMP directory. // We'll deal with that there rather than here. SG_ERR_CHECK( SG_file__open__pathname(pCtx,pPathTempFile,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0400,&pFile) ); SG_ERR_CHECK( SG_repo__fetch_blob_into_file(pCtx, pMrg->pWcTx->pDb->pRepo, pszHidBlob,pFile,NULL) ); SG_FILE_NULLCLOSE(pCtx,pFile); } return; fail: if (pFile) // only if **WE** created the file, do we try to delete it on error. { SG_FILE_NULLCLOSE(pCtx,pFile); SG_ERR_IGNORE( SG_fsobj__remove__pathname(pCtx,pPathTempFile) ); } }
void _set_curl_options(SG_context* pCtx, CURL* pCurl) { char * szServerFiles = NULL; char * szVerifyCerts = NULL; SG_pathname *pServerFiles = NULL; CURLcode rc = CURLE_OK; #ifdef WINDOWS SG_bool bExists = SG_FALSE; SG_bool bVerifyCerts = SG_TRUE; #endif SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__VERIFY_SSL_CERTS, NULL, &szVerifyCerts, NULL) ); if (szVerifyCerts != NULL && (SG_strcmp__null(szVerifyCerts, "false") == 0 || SG_strcmp__null(szVerifyCerts, "FALSE") == 0)) { #ifdef WINDOWS bVerifyCerts = SG_FALSE; #endif rc = curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, SG_FALSE); } if (rc) SG_ERR_THROW(SG_ERR_LIBCURL(rc)); #ifdef WINDOWS if (bVerifyCerts) { SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__SERVER_FILES, NULL, &szServerFiles, NULL) ); if (szServerFiles) { SG_ERR_CHECK( SG_pathname__alloc__sz(pCtx, &pServerFiles, szServerFiles) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pServerFiles, "ssl") ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pServerFiles, "curl-ca-bundle.crt") ); SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pServerFiles, &bExists, NULL, NULL) ); } if (bExists) { rc = curl_easy_setopt(pCurl, CURLOPT_CAINFO, SG_pathname__sz(pServerFiles)); if (rc) SG_ERR_THROW(SG_ERR_LIBCURL(rc)); } else { if (pServerFiles) SG_ERR_CHECK( SG_log__report_warning(pCtx, "Could not find root certificate file. Looked for it at: %s. SSL connections will not work.", SG_pathname__sz(pServerFiles)) ); else SG_ERR_CHECK( SG_log__report_warning(pCtx, "Could not find root certificate file: no server/files path is configured. SSL connections will not work.") ); } } #endif fail: SG_PATHNAME_NULLFREE(pCtx, pServerFiles); SG_NULLFREE(pCtx, szServerFiles); SG_NULLFREE(pCtx, szVerifyCerts); }
/** * Convert absolute path to a wd-top-relative string. * * This is just pathname/string parsing; we DO NOT confirm * that the path exists. We only confirm that the result * is properly contained within the working directory. * */ void sg_wc_db__path__absolute_to_repopath(SG_context * pCtx, const sg_wc_db * pDb, const SG_pathname * pPathItem, SG_string ** ppStringRepoPath) { SG_string * pString = NULL; const char * psz; SG_workingdir__wdpath_to_repopath(pCtx, pDb->pPathWorkingDirectoryTop, pPathItem, SG_FALSE, &pString); if (SG_CONTEXT__HAS_ERR(pCtx)) { if (SG_context__err_equals(pCtx, SG_ERR_CANNOT_MAKE_RELATIVE_PATH)) goto throw_not_in_working_copy; if (SG_context__err_equals(pCtx, SG_ERR_ITEM_NOT_UNDER_VERSION_CONTROL)) goto throw_not_in_working_copy; if (SG_context__err_equals(pCtx, SG_ERR_PATH_NOT_IN_WORKING_COPY)) goto throw_not_in_working_copy; SG_ERR_RETHROW; } psz = SG_string__sz(pString); if ((psz[0] == '.') && (psz[1] == '.') && ((psz[2] == '/') || (psz[2] == 0))) goto throw_not_in_working_copy; *ppStringRepoPath = pString; return; throw_not_in_working_copy: SG_context__err_reset(pCtx); SG_ERR_THROW2( SG_ERR_PATH_NOT_IN_WORKING_COPY, (pCtx, "The path '%s' is not inside the working copy rooted at '%s'.", SG_pathname__sz(pPathItem), SG_pathname__sz(pDb->pPathWorkingDirectoryTop)) ); fail: SG_STRING_NULLFREE(pCtx, pString); }
/** * 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); }
int u0020_utf8pathnames__create_file(SG_context * pCtx, const SG_pathname * pPathnameTmpDir, _tableitem * pti) { // create a file in the given tmp dir using the given filename. SG_pathname * pPathnameNewFile; char * pBufUtf8; SG_uint32 lenUtf8; SG_file * pFile; int iResult; SG_bool bTest; // convert the utf32 string into utf8. VERIFY_ERR_CHECK_DISCARD( SG_utf8__from_utf32(pCtx, pti->pa32,&pBufUtf8,&lenUtf8) ); // we have to free pBufUtf8 // verify that the computed utf8 string matches what we thought it should be. // (this hopefully guards against the conversion layer playing NFC/NFD tricks.) iResult = SG_utf8__compare(pBufUtf8,(char *)pti->pa8); VERIFYP_COND("u0020_utf8pathnames",(iResult==0),("Compare failed [%s][%s]",pBufUtf8,pti->pa8)); // create full pathname to the file to create. VERIFY_ERR_CHECK_DISCARD( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPathnameNewFile, pPathnameTmpDir,pBufUtf8) ); // create the file and close it. // on Linux when our locale is set to something other than UTF-8, we may // get an ICU(10) == U_INVALID_CHAR_FOUND error because the test data is // not necessarily friendly to any one locale and there are some NFD // cases too. we map ICU(10) to SG_ERR_UNMAPPABLE_UNICODE_CHAR SG_file__open__pathname(pCtx,pPathnameNewFile,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0755,&pFile); #if defined(LINUX) bTest = ( (!SG_context__has_err(pCtx)) || (SG_context__err_equals(pCtx,SG_ERR_UNMAPPABLE_UNICODE_CHAR)) ); #else bTest = ( (!SG_context__has_err(pCtx)) ); #endif SG_context__err_reset(pCtx); VERIFYP_COND("u0020_utf8pathnames",bTest, ("Error Creating file [%s]",SG_pathname__sz(pPathnameNewFile))); VERIFY_ERR_CHECK_DISCARD( SG_file__close(pCtx, &pFile) ); SG_PATHNAME_NULLFREE(pCtx, pPathnameNewFile); SG_NULLFREE(pCtx, pBufUtf8); return 1; }
static void _resolve__fix__run_external_file_merge_1(SG_context * pCtx, struct _resolve_data * pData, _resolve__external_tool * pET, _resolve__step_pathnames * pStepPathnames, SG_string * pStrRepoPath, SG_bool * pbMergedText) { SG_exec_argvec * pArgVec = NULL; SG_exit_status exitStatus; SG_UNUSED( pData ); #if 0 && defined(DEBUG) SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, ("RESOLVE File Merge: %s\n" " Mine: %s\n" " Other: %s\n" " Ancestor: %s\n" " Result: %s\n"), SG_string__sz(pStrRepoPath), SG_pathname__sz(pStepPathnames->pPath_Mine), SG_pathname__sz(pStepPathnames->pPath_Other), SG_pathname__sz(pStepPathnames->pPath_Ancestor), SG_pathname__sz(pStepPathnames->pPath_Result)) ); #endif SG_ERR_CHECK( SG_exec_argvec__alloc(pCtx, &pArgVec) ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "-r") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, SG_pathname__sz(pStepPathnames->pPath_Result)) ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "-t1") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "Mine") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "-t2") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, SG_string__sz(pStrRepoPath)) ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "-t3") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, "Other") ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, SG_pathname__sz(pStepPathnames->pPath_Mine)) ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, SG_pathname__sz(pStepPathnames->pPath_Ancestor)) ); SG_ERR_CHECK( SG_exec_argvec__append__sz(pCtx, pArgVec, SG_pathname__sz(pStepPathnames->pPath_Other)) ); SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDOUT, "RESOLVE: Preparing to launch external merge tool: %s\n", pET->pszName) ); SG_ERR_CHECK( SG_exec__exec_sync__files(pCtx, pET->pszExe, pArgVec, NULL, NULL, NULL, &exitStatus) ); *pbMergedText = (exitStatus == 0); fail: SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec); }
SG_bool compare_files_are_identical(const SG_pathname* pPath1, const SG_pathname* pPath2) { SG_bool bResult; FILE* fp1; FILE* fp2; fp1 = fopen(SG_pathname__sz(pPath1), "r"); if (!fp1) { return SG_FALSE; } fp2 = fopen(SG_pathname__sz(pPath2), "r"); if (!fp2) { fclose(fp1); return SG_FALSE; } bResult = SG_TRUE; while (SG_TRUE) { int c1 = fgetc(fp1); int c2 = fgetc(fp2); if (c1 != c2) { bResult = SG_FALSE; break; } if (c1 == EOF) { break; } } fclose(fp1); fclose(fp2); return bResult; }
void MyFn(create_tmp_src_dir)(SG_context * pCtx, SG_pathname ** ppPathnameTempDir) { // create a temp directory in the current directory to be the // home of some userfiles. // caller must free returned value. SG_pathname * pPathnameTempDir = NULL; VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_cwd(pCtx,&pPathnameTempDir) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir_recursive__pathname(pCtx, pPathnameTempDir) ); INFOP("mktmpdir",("Temp Src Dir is [%s]",SG_pathname__sz(pPathnameTempDir))); *ppPathnameTempDir = pPathnameTempDir; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPathnameTempDir); }
void SG_jscore__check_module_dags(SG_context *pCtx, JSContext *cx, JSObject *glob, const char *reponame) { jsval args[2]; JSBool js_ok; jsval rval; JSString *pjs; jsval fo = JSVAL_VOID; if (gpJSCoreGlobalState->bSkipModules || (! gpJSCoreGlobalState->pPathToModules)) return; SG_ERR_CHECK( _sg_jscore__install_modules(pCtx, cx, glob, NULL) ); SG_JS_NULL_CHECK( (pjs = JS_NewStringCopyZ(cx, reponame)) ); args[0] = STRING_TO_JSVAL(pjs); SG_JS_NULL_CHECK( (pjs = JS_NewStringCopyZ(cx, SG_pathname__sz(gpJSCoreGlobalState->pPathToModules))) ); args[1] = STRING_TO_JSVAL(pjs); if (! JS_LookupProperty(cx, glob, "checkModuleDags", &fo)) { SG_ERR_CHECK_CURRENT; SG_ERR_THROW2(SG_ERR_JS, (pCtx, "lookup of checkModuleDags failed")); } if (!JSVAL_IS_VOID(fo)) { js_ok = JS_CallFunctionName(cx, glob, "checkModuleDags", SG_NrElements(args), args, &rval); SG_ERR_CHECK_CURRENT; if(!js_ok) SG_ERR_THROW2(SG_ERR_JS, (pCtx, "An error occurred initializing modules: call to JavaScript checkModuleDags() failed")); } fail: ; }
/** * 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); }
int u0020_utf8pathnames__test(SG_context * pCtx) { SG_pathname * pPathnameTmpDir; int k, kLimit; // create a temporary directory. VERIFY_ERR_CHECK_RETURN( u0020_utf8pathnames__mkdir_tmp_dir(pCtx, &pPathnameTmpDir) ); INFOP("u0020_utf8pathnames",("Creating directory [%s]",SG_pathname__sz(pPathnameTmpDir))); // create a series of files in the temporary directory that have // various unicode characters in their names. kLimit = SG_NrElements(table); for (k=0; k<kLimit; k++) { _tableitem * pti = &table[k]; INFOP("u0020_utf8pathnames",("[%d] starts with [%c]",k,pti->pa8[0])); VERIFY_ERR_CHECK_DISCARD( u0020_utf8pathnames__create_file(pCtx,pPathnameTmpDir,pti) ); } // open the tmp dir for reading and read the filename of each file in it. // compare these with the version of the filename that we used to create // the file. VERIFY_ERR_CHECK_DISCARD( u0020_utf8pathnames__readdir(pCtx, pPathnameTmpDir) ); // clean up our mess VERIFY_ERR_CHECK_DISCARD( SG_fsobj__rmdir_recursive__pathname(pCtx, pPathnameTmpDir) ); SG_PATHNAME_NULLFREE(pCtx, pPathnameTmpDir); return 1; }
void MyFn(create_some_blobs_from_files)(SG_context * pCtx, SG_repo * pRepo, const SG_pathname * pPathnameTempDir) { SG_uint64 k; char * szRepoId; VERIFY_ERR_CHECK_DISCARD( SG_repo__get_repo_id(pCtx, pRepo, &szRepoId) ); INFOP("create_some_blobs_from_files",("RepoID[%s] TempDir[%s] ", szRepoId, SG_pathname__sz(pPathnameTempDir) )); SG_NULLFREE(pCtx, szRepoId); ////////////////////////////////////////////////////////////////// // create a series of blobs of various known lengths and contents. for (k=1; k <= MyMaxFile; k+= MyStepFile) { SG_ERR_IGNORE( MyFn(create_blob_from_file)(pCtx, pRepo,pPathnameTempDir,k,"Hello World!\nThis is line 2.\n") ); SG_ERR_IGNORE( MyFn(create_blob_from_file)(pCtx, pRepo,pPathnameTempDir,k,"Welcome to the middle of the film!\n") ); } }
void SG_vfile__begin( SG_context* pCtx, const SG_pathname* pPath, /**< The path of the file containing the JSON text */ SG_file_flags mode, SG_vhash** ppvh, /**< If there are no errors, the resulting vhash table will be returned here. */ SG_vfile** ppvf ) { SG_vfile* pvf = NULL; SG_vhash* pvh = NULL; SG_uint32 len32; SG_fsobj_type t; SG_byte* p = NULL; SG_bool bExists; SG_fsobj_type FsObjType; SG_fsobj_perms FsObjPerms; SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pPath, &bExists, &FsObjType, &FsObjPerms) ); if ( bExists && (SG_FSOBJ_TYPE__REGULAR != FsObjType) ) { SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE); } if (bExists) { SG_uint64 len64; SG_ERR_CHECK( SG_fsobj__length__pathname(pCtx, pPath, &len64, &t) ); // TODO "len" is uint64 because we can have huge files, but // TODO our buffer is limited to uint32 (on 32bit systems). // TODO verify that len will fit in uint32. len32 = (SG_uint32)len64; } else { len32 = 0; } SG_ERR_CHECK_RETURN( SG_alloc1(pCtx, pvf) ); SG_ERR_CHECK( SG_file__open__pathname(pCtx, pPath, mode | SG_FILE_LOCK, SG_FSOBJ_PERMS__UNUSED, &pvf->pFile) ); pvf->mode = mode; #if TRACE_VFILE SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "VFileBegin: Reading %d bytes from %s\n", len32, SG_pathname__sz(pPath)) ); #endif if (len32 > 0) { SG_ERR_CHECK( SG_alloc(pCtx, 1,len32+1,&p) ); SG_ERR_CHECK( SG_file__read(pCtx, pvf->pFile, len32, p, NULL) ); p[len32] = 0; SG_ERR_CHECK( SG_VHASH__ALLOC__FROM_JSON(pCtx, &pvh, (const char*) p) ); SG_NULLFREE(pCtx, p); p = NULL; } else { pvh = NULL; } *ppvf = pvf; *ppvh = pvh; return; fail: SG_FILE_NULLCLOSE(pCtx, pvf->pFile); SG_NULLFREE(pCtx, p); SG_NULLFREE(pCtx, pvf); }
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); }
static void sg_read_entire_file( SG_context* pCtx, const SG_pathname* pPath, char** ppbuf, SG_uint32* plen ) { SG_uint32 len32; SG_fsobj_type t; SG_byte* p = NULL; SG_bool bExists; SG_fsobj_type FsObjType; SG_fsobj_perms FsObjPerms; SG_file* pFile = NULL; SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pPath, &bExists, &FsObjType, &FsObjPerms) ); if ( bExists && (SG_FSOBJ_TYPE__REGULAR != FsObjType) ) { SG_ERR_IGNORE( SG_log__report_error(pCtx, "Unable to open file: %s.", SG_pathname__sz(pPath)) ); SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE); } if (bExists) { SG_uint64 len64; SG_ERR_CHECK( SG_fsobj__length__pathname(pCtx, pPath, &len64, &t) ); // TODO "len" is uint64 because we can have huge files, but // TODO our buffer is limited to uint32 (on 32bit systems). // TODO verify that len will fit in uint32. len32 = (SG_uint32)len64; SG_ERR_CHECK( SG_file__open__pathname(pCtx, pPath, SG_FILE_RDONLY | SG_FILE_OPEN_EXISTING, SG_FSOBJ_PERMS__UNUSED, &pFile) ); } else { SG_ERR_THROW_RETURN(SG_ERR_NOTAFILE); //len32 = 0; } if (len32 > 0) { SG_ERR_CHECK( SG_alloc(pCtx, 1,len32+1,&p) ); SG_ERR_CHECK( SG_file__read(pCtx, pFile, len32, p, NULL) ); p[len32] = 0; *ppbuf = (char*) p; p = NULL; *plen = len32; } else { *ppbuf = NULL; *plen = 0; } fail: SG_FILE_NULLCLOSE(pCtx, pFile); SG_NULLFREE(pCtx, p); }
/** * Return a pathname (live or temp) to a file that contains * the CURRENTLY QUEUED content that this item **SHOULD** have * at this point in the TX. * * That is, the caller could be in the middle of a TX and have * overwritten the file once or twice and then may now be * requesting the path to show a diff. Or the file content may * be unchanged, but we have queued one or more moves/renames to * it or parent directories. * * As a good player INSIDE THE TX, we need to give them a path * to a CURRENT IN-TX COPY OF THE ***CONTENT*** (wherever it * may be). * * So the path we return may be to a temp file that was created * as a source for a QUEUED overwrite. Or it may be a path to * the unmodified content in the WD -- WHERE IT WAS BEFORE THE * TX -- because until APPLY is called, the WD hasn't been * changed yet. * * Regardless of whether the result is a temp file or not, the * caller should be careful to not let the user modify the file * without participating in the TX. That is, if we return the * actual non-temp working copy of a file and they use it in a * DIFF and the user's difftool is interactive and they alter * it and then we cancel the TX, what should the WD version of * the file contain? * * See also: * __overwrite_file_from_file() * __overwrite_file_from_repo() * __add_special() * __undo_delete() * * * We return an indication of whether the file is a TEMP file * and shouldn't be written to. It DOES NOT indicate that you * can delete it -- it indicates that you should not edit it because * *WE* will probably delete the file if the TX is rolled-back and so * the user would lose their edits. * */ void sg_wc_liveview_item__get_proxy_file_path(SG_context * pCtx, sg_wc_liveview_item * pLVI, SG_wc_tx * pWcTx, SG_pathname ** ppPath, SG_bool * pbIsTmp) { SG_string * pStringRepoPath = NULL; SG_pathname * pPathAbsolute = NULL; char * pszGid = NULL; const char * psz; SG_bool bIsTmp = SG_TRUE; if (pLVI->tneType != SG_TREENODEENTRY_TYPE_REGULAR_FILE) SG_ERR_THROW2_RETURN( SG_ERR_INVALIDARG, (pCtx, "GetProxyFilePath: '%s' is not a file.", SG_string__sz(pLVI->pStringEntryname)) ); if (pLVI->queuedOverwrites.pvhContent == NULL) { // No changes to the content yet in this TX. Return the PRE-TX // pathname of this file. (We may have QUEUED moves/renames on // the file or a parent directory, but they haven't been applied // yet.) SG_ASSERT( pLVI->pPrescanRow ); SG_ASSERT( pLVI->pPrescanRow->pStringEntryname ); SG_ASSERT( pLVI->pPrescanRow->pPrescanDir_Ref ); SG_ASSERT( pLVI->pPrescanRow->pPrescanDir_Ref->pStringRefRepoPath ); SG_ERR_CHECK( SG_STRING__ALLOC__COPY(pCtx, &pStringRepoPath, pLVI->pPrescanRow->pPrescanDir_Ref->pStringRefRepoPath) ); SG_ERR_CHECK( SG_repopath__append_entryname(pCtx, pStringRepoPath, SG_string__sz(pLVI->pPrescanRow->pStringEntryname), SG_FALSE) ); SG_ERR_CHECK( sg_wc_db__path__repopath_to_absolute(pCtx, pWcTx->pDb, pStringRepoPath, &pPathAbsolute) ); bIsTmp = SG_FALSE; // path is to actual WC file goto done; } SG_ERR_CHECK_RETURN( SG_vhash__check__sz(pCtx, pLVI->queuedOverwrites.pvhContent, "file", &psz) ); if (psz) { // return path to existing TEMP file. someone else owns the file. SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &pPathAbsolute, psz) ); bIsTmp = SG_TRUE; // path is to a TEMP file (for which an overwrite-from-file has already been scheduled). goto done; } SG_ERR_CHECK_RETURN( SG_vhash__check__sz(pCtx, pLVI->queuedOverwrites.pvhContent, "hid", &psz) ); if (psz) { // synthesize a TEMP file for this. caller owns the new temp file. SG_ERR_CHECK( sg_wc_db__gid__get_gid_from_alias(pCtx, pWcTx->pDb, pLVI->uiAliasGid, &pszGid) ); SG_ERR_CHECK( sg_wc_diff_utils__export_to_temp_file(pCtx, pWcTx, "ref", pszGid, psz, SG_string__sz(pLVI->pStringEntryname), // for suffix only &pPathAbsolute) ); bIsTmp = SG_TRUE; // path is to a TEMP file that we just created. goto done; } SG_ERR_THROW2_RETURN( SG_ERR_NOTIMPLEMENTED, (pCtx, "GetProxyFilePath: required field missing from vhash for: %s", SG_string__sz(pLVI->pStringEntryname)) ); done: #if TRACE_WC_LIE SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, "GetProxyFilePath: '%s' ==> '%s' [bIsTmp %d]\n", SG_string__sz(pLVI->pStringEntryname), SG_pathname__sz(pPathAbsolute), bIsTmp) ); #endif *ppPath = pPathAbsolute; pPathAbsolute = NULL; *pbIsTmp = bIsTmp; fail: SG_PATHNAME_NULLFREE(pCtx, pPathAbsolute); SG_STRING_NULLFREE(pCtx, pStringRepoPath); SG_NULLFREE(pCtx, pszGid); }
int u0040_unc__stat_dir(SG_context * pCtx, const char * szDir) { SG_pathname * pPathname = NULL; SG_pathname * pPathnameFile = NULL; SG_file * pf = NULL; SG_fsobj_stat fsobjStat; SG_bool bFileExists; SG_int_to_string_buffer bufSize; char bufDate[100]; SG_context__err_reset(pCtx); ////////////////////////////////////////////////////////////////// // stat the given directory. ////////////////////////////////////////////////////////////////// INFOP("u0040_unc",("Inspecting [%s]",szDir)); VERIFY_ERR_CHECK_RETURN( SG_PATHNAME__ALLOC__SZ(pCtx,&pPathname,szDir) ); VERIFY_ERR_CHECK( SG_fsobj__stat__pathname(pCtx,pPathname,&fsobjStat) ); VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__DIRECTORY)); // TODO should we verify length == 0 ? // TODO should we verify modtime ? SG_uint64_to_sz(fsobjStat.size, bufSize); VERIFY_ERR_CHECK_DISCARD( SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate)) ); INFOP("u0040_unc",("Result: [perms %04o][type %d][size %s][mtime %s]", fsobjStat.perms,fsobjStat.type, bufSize,bufDate)); ////////////////////////////////////////////////////////////////// // create a unique file in the directory and stat it. ////////////////////////////////////////////////////////////////// VERIFY_ERR_CHECK( unittest__alloc_unique_pathname(pCtx,szDir,&pPathnameFile) ); INFOP("u0040_unc",(" Creating file [%s]",SG_pathname__sz(pPathnameFile))); VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathnameFile,SG_FILE_CREATE_NEW | SG_FILE_RDWR,0777,&pf) ); VERIFY_ERR_CHECK( SG_fsobj__stat__pathname(pCtx,pPathnameFile,&fsobjStat) ); VERIFY_COND("u0040_unc",(fsobjStat.type == SG_FSOBJ_TYPE__REGULAR)); VERIFY_COND("u0040_unc",(fsobjStat.size == 0)); VERIFY_COND("u0040_unc",(SG_fsobj__equivalent_perms(fsobjStat.perms,0777))); // TODO should we verify modtime ? SG_uint64_to_sz(fsobjStat.size, bufSize); VERIFY_ERR_CHECK_DISCARD( SG_time__format_utc__i64(pCtx,fsobjStat.mtime_ms,bufDate,SG_NrElements(bufDate)) ); INFOP("u0040_unc",(" Result: [perms %04o][type %d][size %s][mtime %s]", fsobjStat.perms,fsobjStat.type, bufSize,bufDate)); VERIFY_ERR_CHECK_DISCARD( SG_file__close(pCtx, &pf) ); // delete the file and stat it again VERIFY_ERR_CHECK_DISCARD( SG_fsobj__remove__pathname(pCtx,pPathnameFile) ); VERIFY_ERR_CHECK_DISCARD( SG_fsobj__exists__pathname(pCtx,pPathnameFile,&bFileExists,NULL,NULL) ); VERIFY_COND("u0040_unc",(!bFileExists)); ////////////////////////////////////////////////////////////////// // clean up ////////////////////////////////////////////////////////////////// SG_PATHNAME_NULLFREE(pCtx, pPathnameFile); SG_PATHNAME_NULLFREE(pCtx, pPathname); return 1; fail: SG_FILE_NULLCLOSE(pCtx, pf); SG_PATHNAME_NULLFREE(pCtx, pPathnameFile); SG_PATHNAME_NULLFREE(pCtx, pPathname); return 0; }
/** * Assuming that we have something of the form: * * vv resolve [--foo] <arg_0> [<arg_1> [<arg_2> ...]] * * where each <arg_x> is an absolute or relative path in the WD * (probably not a repo-path). * * Use the PENDINGTREE to lookup each path and get the entry's GID. * Use the GID to search for an ISSUE in the list of issues. If we * find it, add the GID to the stringarray we are building. If not, * throw an error. */ static void _resolve__map_args_to_gids(SG_context * pCtx, struct _resolve_data * pData, SG_uint32 count_args, const char ** paszArgs, SG_bool bWantResolved, SG_bool bWantUnresolved) { SG_pathname * pPath_k = NULL; char * pszGid_k = NULL; SG_uint32 kArg; SG_bool bWantBoth = (bWantResolved && bWantUnresolved); SG_ERR_CHECK( SG_STRINGARRAY__ALLOC(pCtx, &pData->psaGids, count_args) ); for (kArg=0; kArg<count_args; kArg++) { const SG_vhash * pvhIssue_k; SG_bool bFound; SG_bool bDuplicate; SG_bool bWantThisOne; // take each <arg_k> and get a full pathname for it and // search for it in the pendingtree and get its GID. // in theory, if an entry has an issue, it is dirty and // should have a ptnode. if (paszArgs[kArg][0] == '@') SG_ERR_CHECK( SG_workingdir__construct_absolute_path_from_repo_path2(pCtx, pData->pPendingTree, paszArgs[kArg], &pPath_k) ); else SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &pPath_k, paszArgs[kArg]) ); SG_ERR_CHECK( SG_pendingtree__get_gid_from_local_path(pCtx, pData->pPendingTree, pPath_k, &pszGid_k) ); #if 0 && defined(DEBUG) SG_ERR_IGNORE( SG_console(pCtx, SG_CS_STDERR, ("Mapped arg[%d] '%s' to:\n" "\t%s\n" "\t[gid %s]\n"), kArg, paszArgs[kArg], SG_pathname__sz(pPath_k), pszGid_k) ); #endif // see if there is an ISSUE for this GID. SG_ERR_CHECK( SG_pendingtree__find_wd_issue_by_gid(pCtx, pData->pPendingTree, pszGid_k, &bFound, &pvhIssue_k) ); if (!bFound) SG_ERR_THROW2( SG_ERR_ISSUE_NOT_FOUND, (pCtx, "No issue found for '%s': %s", paszArgs[kArg], SG_pathname__sz(pPath_k)) ); if (bWantBoth) bWantThisOne = SG_TRUE; else { SG_int64 s; SG_pendingtree_wd_issue_status status; SG_bool bResolved; SG_ERR_CHECK_RETURN( SG_vhash__get__int64(pCtx, pvhIssue_k, "status", &s) ); status = (SG_pendingtree_wd_issue_status)s; bResolved = ((status & SG_ISSUE_STATUS__MARKED_RESOLVED) == SG_ISSUE_STATUS__MARKED_RESOLVED); bWantThisOne = ((bWantResolved && bResolved) || (bWantUnresolved && !bResolved)); } if (bWantThisOne) { // check for duplicate args on command line. (or rather, args that // map to the same GID.) SG_ERR_CHECK( SG_stringarray__find(pCtx, pData->psaGids, pszGid_k, 0, &bDuplicate, NULL) ); if (bDuplicate) SG_ERR_THROW2( SG_ERR_DUPLICATE_ISSUE, (pCtx, "Argument '%s' maps to an issue already named.", paszArgs[kArg]) ); SG_ERR_CHECK( SG_stringarray__add(pCtx, pData->psaGids, pszGid_k) ); } SG_NULLFREE(pCtx, pszGid_k); SG_PATHNAME_NULLFREE(pCtx, pPath_k); } return; fail: SG_NULLFREE(pCtx, pszGid_k); SG_PATHNAME_NULLFREE(pCtx, pPath_k); }
static void perform_upload_request__string( SG_context* pCtx, CFHTTPMessageRef myRequest, SG_pathname* pPath, CFHTTPMessageRef* pmyResponse, SG_string** ppstr ) { CFReadStreamRef myReadStream = NULL; CFHTTPMessageRef myResponse = NULL; SG_string* pstr = NULL; CFReadStreamRef upload = NULL; CFURLRef upload_file_url = NULL; // set the content-length header { SG_uint64 len = 0; SG_ERR_CHECK( SG_fsobj__length__pathname(pCtx, pPath, &len, NULL) ); CFStringRef headerFieldName = CFSTR("Content-Length"); CFStringRef headerFieldValue = CFStringCreateWithFormat (kCFAllocatorDefault, NULL, CFSTR("%d"), len); CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue); CFRelease(headerFieldValue); } upload_file_url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*) SG_pathname__sz(pPath), SG_STRLEN(SG_pathname__sz(pPath)), SG_FALSE); upload = CFReadStreamCreateWithFile(kCFAllocatorDefault, upload_file_url); CFRelease(upload_file_url); if (!CFReadStreamOpen(upload)) { CFStreamError myErr = CFReadStreamGetError(upload); if (myErr.domain == kCFStreamErrorDomainPOSIX) { // Interpret myErr.error as a UNIX errno. SG_ERR_THROW( SG_ERR_ERRNO(myErr.error) ); } else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) { // Interpret myErr.error as a MacOS error code. // TODO SG_ERR_THROW( SG_ERR_MAC((OSStatus) myErr.error) ); SG_ERR_THROW( SG_ERR_UNSPECIFIED ); } } SG_ERR_CHECK( send_upload_request(pCtx, myRequest, upload, &myReadStream) ); SG_ERR_CHECK( read_entire_stream__string(pCtx, myReadStream, &pstr, &myResponse) ); *ppstr = pstr; pstr = NULL; *pmyResponse = myResponse; myResponse = NULL; fail: if (upload) { CFRelease(upload); } if (myReadStream) { CFReadStreamClose(myReadStream); CFRelease(myReadStream); myReadStream = NULL; } if (myResponse) { CFRelease(myResponse); myResponse = NULL; } SG_STRING_NULLFREE(pCtx, pstr); }
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); }
/** * create 1 test file. * cat it to a second file using files bound to child's STDIN and STDOUT. * cat both files to third file using cl args for input and third bound to child's STDOUT. * cat all 3 files using cl args to OUR STDOUT. */ void MyFn(test1)(SG_context * pCtx) { SG_exit_status exitStatusChild; SG_file * pFileF1 = NULL; SG_file * pFileF2 = NULL; SG_file * pFileF3 = NULL; SG_pathname * pPathTempDir = NULL; SG_pathname * pPathF1 = NULL; SG_pathname * pPathF2 = NULL; SG_pathname * pPathF3 = NULL; SG_exec_argvec * pArgVec = NULL; // create a GID temp directory in the current directory. VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_cwd(pCtx,&pPathTempDir) ); VERIFY_ERR_CHECK( SG_fsobj__mkdir_recursive__pathname(pCtx,pPathTempDir) ); // create a couple of pathnames to test files in the temp directory. VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF1) ); INFOP("exec",("PathF1 is %s",SG_pathname__sz(pPathF1))); VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF2) ); INFOP("exec",("PathF2 is %s",SG_pathname__sz(pPathF2))); VERIFY_ERR_CHECK( unittest__alloc_unique_pathname_in_dir(pCtx,SG_pathname__sz(pPathTempDir),&pPathF3) ); INFOP("exec",("PathF3 is %s",SG_pathname__sz(pPathF3))); ////////////////////////////////////////////////////////////////// // create F1 and write some data to it. VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathF1,SG_FILE_WRONLY|SG_FILE_CREATE_NEW,0644,&pFileF1) ); VERIFY_ERR_CHECK( SG_file__write(pCtx,pFileF1, SG_pathname__length_in_bytes(pPathF1), (SG_byte *)SG_pathname__sz(pPathF1), NULL) ); VERIFY_ERR_CHECK( SG_file__write(pCtx,pFileF1, 1, (SG_byte *)"\n", NULL) ); VERIFY_ERR_CHECK( SG_file__write(pCtx,pFileF1, SG_pathname__length_in_bytes(pPathF1), (SG_byte *)SG_pathname__sz(pPathF1), NULL) ); VERIFY_ERR_CHECK( SG_file__write(pCtx,pFileF1, 1, (SG_byte *)"\n", NULL) ); SG_FILE_NULLCLOSE(pCtx, pFileF1); ////////////////////////////////////////////////////////////////// // re-open F1 for reading. // create F2 as a place for STDOUT of command. VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathF1,SG_FILE_RDONLY|SG_FILE_OPEN_EXISTING,0644,&pFileF1) ); VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathF2,SG_FILE_WRONLY|SG_FILE_CREATE_NEW, 0644,&pFileF2) ); // exec: /bin/cat <f1 >f2 VERIFY_ERR_CHECK( SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,NULL,pFileF1,pFileF2,NULL,&exitStatusChild) ); VERIFY_COND("child status",(exitStatusChild == 0)); INFOP("/bin/cat <f1 >f2",("Child exit status is [%d]",exitStatusChild)); SG_FILE_NULLCLOSE(pCtx, pFileF1); SG_FILE_NULLCLOSE(pCtx, pFileF2); ////////////////////////////////////////////////////////////////// // let F1 and F2 be given on the command line. // create F3 as a place for STDOUT of command. VERIFY_ERR_CHECK( SG_file__open__pathname(pCtx,pPathF3,SG_FILE_WRONLY|SG_FILE_CREATE_NEW, 0644,&pFileF3) ); // exec: /bin/cat -n f1 f2 >f3 VERIFY_ERR_CHECK( SG_exec_argvec__alloc(pCtx,&pArgVec) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,"-n") ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1)) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2)) ); VERIFY_ERR_CHECK( SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,pFileF3,NULL,&exitStatusChild) ); VERIFY_COND("child status",(exitStatusChild == 0)); INFOP("/bin/cat -n f1 f2 >f3",("Child exit status is [%d]",exitStatusChild)); SG_FILE_NULLCLOSE(pCtx, pFileF3); SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec); ////////////////////////////////////////////////////////////////// // exec: /bin/cat f1 f2 f3 (to our stdout) VERIFY_ERR_CHECK( SG_exec_argvec__alloc(pCtx,&pArgVec) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1)) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2)) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF3)) ); VERIFY_ERR_CHECK( SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,NULL,NULL,&exitStatusChild) ); VERIFY_COND("child status",(exitStatusChild == 0)); INFOP("/bin/cat -n f1 f2 f3",("Child exit status is [%d]",exitStatusChild)); SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec); ////////////////////////////////////////////////////////////////// // exec: /bin/cat f3 f2 f1 (to our stdout) VERIFY_ERR_CHECK( SG_exec_argvec__alloc(pCtx,&pArgVec) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF3)) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF2)) ); VERIFY_ERR_CHECK( SG_exec_argvec__append__sz(pCtx,pArgVec,SG_pathname__sz(pPathF1)) ); VERIFY_ERR_CHECK( SG_exec__exec_sync__files(pCtx,MY_CAT_COMMAND,pArgVec,NULL,NULL,NULL,&exitStatusChild) ); VERIFY_COND("child status",(exitStatusChild == 0)); INFOP("/bin/cat -n f3 f2 f1",("Child exit status is [%d]",exitStatusChild)); SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec); // fall through to common cleanup. fail: SG_EXEC_ARGVEC_NULLFREE(pCtx, pArgVec); SG_PATHNAME_NULLFREE(pCtx, pPathTempDir); SG_PATHNAME_NULLFREE(pCtx, pPathF1); SG_PATHNAME_NULLFREE(pCtx, pPathF2); SG_PATHNAME_NULLFREE(pCtx, pPathF3); SG_FILE_NULLCLOSE(pCtx, pFileF1); SG_FILE_NULLCLOSE(pCtx, pFileF2); SG_FILE_NULLCLOSE(pCtx, pFileF3); }