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);
}
Пример #3
0
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);
}
Пример #5
0
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);
}