void sg_wc_db__path__sz_repopath_to_absolute(SG_context * pCtx, const sg_wc_db * pDb, const char * pszRepoPath, SG_pathname ** ppPathItem) { SG_pathname * pPath = NULL; // TODO 2012/01/23 This code was written before the extended-prefix repo-path // TODO stuff, but it is still valid to require a live/wd-relative // TODO repo-path when building an absolute pathname (because it // TODO probably doesn't make sense to convert an arbitrary-context // TODO repo-path (without someone doing the implied context conversion)). // TODO // TODO So I'm going to leave this as an assert for now. SG_ASSERT_RELEASE_FAIL( ((pszRepoPath[0]=='@') && (pszRepoPath[1]=='/')) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__COPY(pCtx, &pPath, pDb->pPathWorkingDirectoryTop) ); SG_ERR_CHECK( SG_pathname__add_final_slash(pCtx, pPath) ); if (pszRepoPath[2]) SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pPath, &pszRepoPath[2]) ); *ppPathItem = pPath; return; fail: SG_PATHNAME_NULLFREE(pCtx, pPath); }
/** * 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 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); }
/** * 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); }
void SG_workingdir__find_mapping( SG_context* pCtx, const SG_pathname* pPathLocalDirectory, SG_pathname** ppPathMappedLocalDirectory, /**< Return the actual local directory that contains the mapping */ SG_string** ppstrNameRepoInstanceDescriptor, /**< Return the name of the repo instance descriptor */ char** ppszidGidAnchorDirectory /**< Return the GID of the repo directory */ ) { SG_pathname* curpath = NULL; SG_string* result_pstrDescriptorName = NULL; char* result_pszidGid = NULL; SG_pathname* result_mappedLocalDirectory = NULL; SG_vhash* pvhMapping = NULL; SG_pathname* pDrawerPath = NULL; SG_pathname* pMappingFilePath = NULL; SG_vhash* pvh = NULL; SG_NULLARGCHECK_RETURN(pPathLocalDirectory); SG_ERR_CHECK( SG_PATHNAME__ALLOC__COPY(pCtx, &curpath, pPathLocalDirectory) ); /* it's a directory, so it should have a final slash */ SG_ERR_CHECK( SG_pathname__add_final_slash(pCtx, curpath) ); while (SG_TRUE) { SG_ERR_CHECK( SG_workingdir__get_drawer_path(pCtx, curpath, &pDrawerPath) ); SG_fsobj__verify_directory_exists_on_disk__pathname(pCtx, pDrawerPath); if (!SG_context__has_err(pCtx)) { const char* pszDescriptorName = NULL; const char* pszGid = NULL; SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pMappingFilePath, pDrawerPath, "repo.json") ); SG_PATHNAME_NULLFREE(pCtx, pDrawerPath); SG_ERR_CHECK( SG_vfile__slurp(pCtx, pMappingFilePath, &pvh) ); SG_ERR_CHECK( SG_vhash__get__vhash(pCtx, pvh, "mapping", &pvhMapping) ); SG_PATHNAME_NULLFREE(pCtx, pMappingFilePath); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhMapping, "descriptor", &pszDescriptorName) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvhMapping, "anchor", &pszGid) ); SG_ERR_CHECK( SG_STRING__ALLOC(pCtx, &result_pstrDescriptorName) ); SG_ERR_CHECK( SG_string__set__sz(pCtx, result_pstrDescriptorName, pszDescriptorName) ); if (pszGid) { SG_ERR_CHECK( SG_gid__alloc_clone(pCtx, pszGid, &result_pszidGid) ); } else { result_pszidGid = NULL; } SG_VHASH_NULLFREE(pCtx, pvh); result_mappedLocalDirectory = curpath; curpath = NULL; break; } else SG_context__err_reset(pCtx); SG_PATHNAME_NULLFREE(pCtx, pDrawerPath); SG_pathname__remove_last(pCtx, curpath); if (SG_context__err_equals(pCtx, SG_ERR_CANNOTTRIMROOTDIRECTORY)) { SG_context__err_reset(pCtx); break; } else { SG_ERR_CHECK_CURRENT; } } if (result_mappedLocalDirectory) { if (ppPathMappedLocalDirectory) { *ppPathMappedLocalDirectory = result_mappedLocalDirectory; } else { SG_PATHNAME_NULLFREE(pCtx, result_mappedLocalDirectory); } if (ppstrNameRepoInstanceDescriptor) { *ppstrNameRepoInstanceDescriptor = result_pstrDescriptorName; } else { SG_STRING_NULLFREE(pCtx, result_pstrDescriptorName); } if (ppszidGidAnchorDirectory) { *ppszidGidAnchorDirectory = result_pszidGid; } else { SG_NULLFREE(pCtx, result_pszidGid); } return; } else { SG_PATHNAME_NULLFREE(pCtx, curpath); SG_ERR_THROW_RETURN(SG_ERR_NOT_FOUND); } fail: SG_VHASH_NULLFREE(pCtx, pvh); SG_PATHNAME_NULLFREE(pCtx, pDrawerPath); SG_PATHNAME_NULLFREE(pCtx, pMappingFilePath); SG_PATHNAME_NULLFREE(pCtx, result_mappedLocalDirectory); SG_PATHNAME_NULLFREE(pCtx, curpath); }