static void _sg_jscore_getpaths(SG_context *pCtx)
{
	char * szServerFiles = NULL;

	if (gpJSCoreGlobalState->pPathToDispatchDotJS)
		return;

	// Figure out and store relavant paths...
	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, &gpJSCoreGlobalState->pPathToDispatchDotJS, szServerFiles)  );
		SG_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToDispatchDotJS, "dispatch.js")  );

		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &gpJSCoreGlobalState->pPathToCore, szServerFiles)  );
		SG_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToCore, "core")  );

		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &gpJSCoreGlobalState->pPathToModules, szServerFiles)  );
		SG_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToModules, "modules")  );
	}

fail:
	SG_NULLFREE(pCtx, szServerFiles);
}
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);
}
/**
 * Initialize a WD (create .sgdrawer and friends) and set up shop.
 * The given directory pathname can either be to a new (to be created)
 * directory -or- an existing (possibly non-empty) directory.
 *
 * WARNING: This routine deviates from the model of the other SG_wc__
 * WARNING: routines because the WD does not yet exist (and we haven't
 * WARNING: yet created .sgdrawer).  The caller may have already created
 * WARNING: an empty directory for us, but that is it.
 *
 * WARNING: This routine also deviates in that we *ONLY* provide a wc8api
 * WARNING: version and *NOT* a wc7txapi version.  Likewise we only provide
 * WARNING: a sg.wc.initialize() version and not a sg_wc_tx.initialize() version.
 * WARNING: This is because I want it to be a complete self-contained
 * WARNING: operation (and I want to hide the number of SQL TXs that are
 * WARNING: required to get everything set up).
 *
 * Also, the given path (to the new WD root) can be an absolute or
 * relative path or NULL (we'll substitute the CWD).  Unlike the other
 * API routines, it cannot be a repo-path.
 *
 * This should only be used by 'vv init' or sg.vv2.init_new_repo()
 * (after the repo has been created).
 *
 */
void SG_wc__initialize(SG_context * pCtx,
                       const char * pszRepoName,
                       const char * pszPath,
                       const char * pszHidCSet,
                       const char * pszTargetBranchName)
{
    SG_wc_tx * pWcTx = NULL;

    SG_NONEMPTYCHECK_RETURN( pszRepoName );		// repo-name is required
    // pszPath is optional; default to CWD.
    SG_NONEMPTYCHECK_RETURN( pszHidCSet );
    // pszTargetBranchName is optional; default to unattached.

    // Create the WD root, the drawer, and the SQL DB.
    // Load the given CSET into the tne_L0 table.
    //
    // We DO NOT create a timestamp cache at this time
    // because of clock blurr problem.  (We can't trust
    // mtime until about 2 seconds after we create the
    // files.)

    SG_ERR_CHECK(  SG_WC_TX__ALLOC__BEGIN__CREATE(pCtx, &pWcTx, pszRepoName, pszPath,
                   SG_FALSE, pszHidCSet)  );
    if (pszTargetBranchName)
    {
        SG_ERR_CHECK(  sg_wc_db__branch__attach(pCtx, pWcTx->pDb, pszTargetBranchName,
                                                SG_VC_BRANCHES__CHECK_ATTACH_NAME__DONT_CARE, SG_TRUE)  );
    }

#if defined(DEBUG)
#define DEBUG_INIT_FAILURE__E2 "gb54c5ca2cfe349eaa3ce599100d1c4d737052960d1e411e1a51e002500da2b78.test"
    {
        // Force a failure while we are initializing a new repo using the current directory in
        // order to test the cleanup/recovery code.
        // See st_wc_checkout_W7885.js
        SG_bool bExists = SG_FALSE;
        SG_pathname * pPathTest = NULL;
        SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathTest, DEBUG_INIT_FAILURE__E2)  );
        SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx, pPathTest, &bExists, NULL, NULL)  );
        SG_PATHNAME_NULLFREE(pCtx, pPathTest);
        if (bExists)
            SG_ERR_THROW2(  SG_ERR_DEBUG_1, (pCtx, "Init: %s", DEBUG_INIT_FAILURE__E2)  );
    }
#endif

    SG_ERR_CHECK(  _check_for_nested_drawer(pCtx, pWcTx)  );

    SG_ERR_CHECK(  SG_wc_tx__apply(pCtx, pWcTx)  );
    SG_ERR_CHECK(  SG_wc_tx__free(pCtx, pWcTx)  );
    return;

fail:
    SG_ERR_IGNORE(  SG_wc_tx__abort_create_and_free(pCtx, &pWcTx)  );
}
/**
 * Select an appropriate difftool to use on this file.
 * We require that the common and right-side fields of
 * pvhDiffItem be filled in first.  (The left-side fields
 * can be after this is called.)
 *
 */
static void _pick_tool(SG_context * pCtx,
					   sg_wc6diff__setup_data * pData,
					   const SG_vhash * pvhItem,
					   SG_vhash * pvhDiffItem,
					   SG_string * pStringHeader)
{
	SG_filetool * pTool = NULL;
	const char * pszRepoPath_live = NULL;
	const char * pszAbsPath = NULL;
	SG_pathname * pPathname = NULL;
	const char * pszToolNameChosen = NULL;
	SG_bool bIsTmp_right = SG_FALSE;

	// use the suffix on the (always present) live-repo-path (rather than
	// the left- or right- version) to pick a tool.
	// 
	// if that fails, use the suffix of current file in the WD
	// (provided it isn't a temp file).  the left side is always
	// a temp file, so don't bother with it.

	SG_ERR_CHECK(  SG_vhash__check__sz(pCtx, pvhItem, "path", &pszRepoPath_live)  );
	SG_ERR_CHECK(  SG_vhash__check__bool(pCtx, pvhDiffItem, "right_is_temp", &bIsTmp_right)  );
	if (!bIsTmp_right)
	{
		SG_ERR_CHECK(  SG_vhash__check__sz(pCtx, pvhDiffItem, "right_abs_path", &pszAbsPath)  );
		if (pszAbsPath)
			SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathname, pszAbsPath)  );
	}

	SG_ERR_CHECK(  SG_difftool__select(pCtx,
									   pData->pszDiffToolContext, // gui or console
									   pszRepoPath_live,          // current/live repo-path
									   pPathname,                 // live or temp absolute pathname
									   pData->pszTool,            // suggested/requested tool
									   pData->pWcTx->pDb->pRepo,
									   &pTool)  );
	if (pTool)
	{
		SG_ERR_CHECK(  SG_filetool__get_name(pCtx, pTool, &pszToolNameChosen)  );
		SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pvhDiffItem, "tool", pszToolNameChosen)  );
		SG_ERR_CHECK(  SG_vhash__add__string__sz(pCtx, pvhDiffItem, "context", pData->pszDiffToolContext)  );
	}
	else
	{
		SG_ERR_CHECK(  SG_string__append__format(pCtx, pStringHeader,
												 "=== No difftool configured for ('%s', '%s') in context '%s'.\n",
												 pszRepoPath_live, pszAbsPath, pData->pszDiffToolContext)  );
	}

fail:
	SG_FILETOOL_NULLFREE(pCtx, pTool);
	SG_PATHNAME_NULLFREE(pCtx, pPathname);
}
void u0038_test_version(SG_context * pCtx)
{
	/* This test pokes around in closet internals in ways normal closet callers shouldn't. */

	SG_string* pstrEnv = NULL;
	SG_uint32 len;
	SG_pathname* pPathCloset = NULL;
	SG_pathname* pPathClosetVersion = NULL;
	SG_pathname* pPathClosetVersionBackup = NULL;
	SG_file* pFile = NULL;
	SG_vhash* pvh = NULL;
	
	/* Deliberately making this break for closet version 3 -- current is version 2. */
	SG_byte buf[3]; 
	
	VERIFY_ERR_CHECK(  SG_environment__get__str(pCtx, "SGCLOSET", &pstrEnv, &len)  );
	if (len)
	{
		VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathCloset, SG_string__sz(pstrEnv))  );
	}
	else
	{
		VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__USER_APPDATA_DIRECTORY(pCtx, &pPathCloset)  );
		VERIFY_ERR_CHECK(  SG_pathname__append__from_sz(pCtx, pPathCloset, ".sgcloset")  );
	}

	VERIFY_ERR_CHECK(  SG_pathname__alloc__pathname_sz(pCtx, &pPathClosetVersion, pPathCloset, "version")  );
	VERIFY_ERR_CHECK(  SG_pathname__alloc__pathname_sz(pCtx, &pPathClosetVersionBackup, pPathCloset, "version.bak")  );

	VERIFY_ERR_CHECK(  SG_fsobj__move__pathname_pathname(pCtx, pPathClosetVersion, pPathClosetVersionBackup)  );
	
	VERIFY_ERR_CHECK(  SG_file__open__pathname(pCtx, pPathClosetVersion, SG_FILE_OPEN_OR_CREATE|SG_FILE_WRONLY|SG_FILE_TRUNC, 0644, &pFile)  );
	VERIFY_ERR_CHECK(  SG_file__write(pCtx, pFile, sizeof(buf), buf, NULL)  ); 
	VERIFY_ERR_CHECK(  SG_file__close(pCtx, &pFile)  );

	SG_closet__descriptors__list(pCtx, &pvh);
	VERIFY_COND("", SG_context__err_equals(pCtx, SG_ERR_UNSUPPORTED_CLOSET_VERSION));
	SG_ERR_DISCARD;

	VERIFY_ERR_CHECK(  SG_fsobj__remove__pathname(pCtx, pPathClosetVersion)  );
	VERIFY_ERR_CHECK(  SG_fsobj__move__pathname_pathname(pCtx, pPathClosetVersionBackup, pPathClosetVersion)  );

	/* Common cleanup */
fail:
	SG_STRING_NULLFREE(pCtx, pstrEnv);
	SG_PATHNAME_NULLFREE(pCtx, pPathCloset);
	SG_PATHNAME_NULLFREE(pCtx, pPathClosetVersion);
	SG_PATHNAME_NULLFREE(pCtx, pPathClosetVersionBackup);
	SG_FILE_NULLCLOSE(pCtx, pFile);
	SG_VHASH_NULLFREE(pCtx, pvh);
}
Beispiel #6
0
void SG_getopt__set_app_name(SG_context * pCtx, SG_getopt * pGetopt, ARGV_CHAR_T * pBuf)
{
	SG_pathname *tp = NULL;
	SG_string *st = NULL;

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &st)  );
	SG_ERR_CHECK(  SG_UTF8__INTERN_FROM_OS_BUFFER(pCtx,st,pBuf)  );

	SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &tp, SG_string__sz(st))  );
	SG_STRING_NULLFREE(pCtx, st);

	SG_STRING_NULLFREE(pCtx, pGetopt->pStringAppName);

	SG_ERR_CHECK(  SG_pathname__get_last(pCtx, tp, &pGetopt->pStringAppName)  );

fail:
	SG_STRING_NULLFREE(pCtx, st);
	SG_PATHNAME_NULLFREE(pCtx, tp);
}
/**
 * Create a new repo and *always* create a WD for it.
 *
 */
void vv2__do_cmd_init_new_repo(SG_context * pCtx,
							  const char * pszRepoName,
							  const char * pszFolder,
							  const char * pszStorage,
							  const char * pszHashMethod,
							  const char * psz_shared_users)
{
	SG_pathname * pPathLocalDirectory = NULL;

	SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathLocalDirectory, pszFolder)  );
	SG_workingdir__find_mapping(pCtx, pPathLocalDirectory, NULL, NULL, NULL);
	SG_ERR_CHECK_CURRENT_DISREGARD(SG_ERR_NOT_A_WORKING_COPY);

	SG_ERR_CHECK(  SG_vv2__init_new_repo(pCtx,
										 pszRepoName,
										 pszFolder,
										 pszStorage,
										 pszHashMethod,
										 SG_FALSE,			// bNoWD
										 psz_shared_users,
										 SG_FALSE,
										 NULL,
										 NULL)  );

fail:
	SG_PATHNAME_NULLFREE(pCtx, pPathLocalDirectory);

	// TODO 2010/10/25 Decide which error message we should try to provide a better error message for.
	// TODO            Candidates include
	// TODO SG_ERR_INVALID_REPO_NAME
	// TODO SG_ERR_AMBIGUOUS_ID_PREFIX
	// TODO SG_ERR_MULTIPLE_HEADS_FROM_DAGNODE
	// TODO
	// TODO            But we should look and see what the lower layers are throwing now.  Some of
	// TODO            of the messages that were here are now being handled.
	return;
}
static void _set_up_logging(
	SG_context * pCtx,
	SG_log_console__data * pcLogStdData,
	SG_log_text__data * pcLogFileData,
	SG_log_text__writer__daily_path__data * pcLogFileWriterData)
{
	// Code coppied from _my_main() in sg.c

	char * szLogLevel = NULL;
	char * szLogPath = NULL;
	SG_uint32							  logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__ALL;
	// find the appropriate log path
	SG_ERR_CHECK(  SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__LOG_PATH, NULL, &szLogPath, NULL)  );


	// get the configured log level
	SG_ERR_CHECK(  SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__LOG_LEVEL, NULL, &szLogLevel, NULL)  );

	// register the stdout logger
	SG_ERR_CHECK(  SG_log_console__set_defaults(pCtx, pcLogStdData)  );
	SG_ERR_CHECK(  SG_log_console__register(pCtx, pcLogStdData, NULL, SG_LOG__FLAG__HANDLER_TYPE__NORMAL)  );

	// register the file logger
	SG_ERR_CHECK(  SG_log_text__set_defaults(pCtx, pcLogFileData)  );
	pcLogFileData->fWriter             = SG_log_text__writer__daily_path;
	pcLogFileData->pWriterData         = pcLogFileWriterData;
	pcLogFileData->szRegisterMessage   = NULL;
	pcLogFileData->szUnregisterMessage = NULL;
	if (szLogLevel != NULL)
	{
		if (SG_stricmp(szLogLevel, "quiet") == 0)
		{
			logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__QUIET;
			pcLogFileData->bLogVerboseOperations = SG_FALSE;
			pcLogFileData->bLogVerboseValues     = SG_FALSE;
			pcLogFileData->szVerboseFormat       = NULL;
			pcLogFileData->szInfoFormat          = NULL;
		}
		else if (SG_stricmp(szLogLevel, "normal") == 0)
		{
			logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__NORMAL;
			pcLogFileData->bLogVerboseOperations = SG_FALSE;
			pcLogFileData->bLogVerboseValues     = SG_FALSE;
			pcLogFileData->szVerboseFormat       = NULL;
		}
		else if (SG_stricmp(szLogLevel, "verbose") == 0)
		{
			logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__ALL;
			pcLogFileData->szRegisterMessage   = "---- vscript started logging ----";
			pcLogFileData->szUnregisterMessage = "---- vscript stopped logging ----";
		}
	}
	logFileFlags |= SG_LOG__FLAG__DETAILED_MESSAGES;
	SG_ERR_CHECK(  SG_log_text__writer__daily_path__set_defaults(pCtx, pcLogFileWriterData)  );
	pcLogFileWriterData->bReopen          = SG_FALSE;
	pcLogFileWriterData->ePermissions     = 0666;
	if (szLogPath != NULL)
		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pcLogFileWriterData->pBasePath, szLogPath)  );
	else
		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__LOG_DIRECTORY(pCtx, &pcLogFileWriterData->pBasePath)  );
	pcLogFileWriterData->szFilenameFormat = "vscript-%d-%02d-%02d.log";
	SG_ERR_CHECK(  SG_log_text__register(pCtx, pcLogFileData, NULL, logFileFlags)  );

fail:
	SG_context__err_reset(pCtx);

	SG_NULLFREE(pCtx, szLogPath);
	SG_NULLFREE(pCtx, szLogLevel);
}
Beispiel #9
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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}
/**
 * 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);
}
void u0052_zip__test_1(SG_context * pCtx)
{
    SG_zip* pzip = NULL;
    SG_unzip* punzip = NULL;
    char buf_tid[SG_TID_MAX_BUFFER_LENGTH];
    SG_pathname* pPath = NULL;
    SG_uint32 count = 0;
    SG_byte buf[256];
    SG_uint32 iBytesRead;
    SG_bool b;
    const char* psz_name = NULL;
    SG_uint64 iLen = 0;

    VERIFY_ERR_CHECK(  SG_tid__generate2(pCtx, buf_tid, sizeof(buf_tid), 32)  );
    VERIFY_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPath, buf_tid)  );

    /* ---------------------------------------------------------------- */
    /* Create the zip file */
    /* ---------------------------------------------------------------- */
    VERIFY_ERR_CHECK(  SG_zip__open(pCtx, pPath, &pzip)  );

#define FILE1_CONTENTS "hello world"
    VERIFY_ERR_CHECK(  SG_zip__begin_file(pCtx, pzip, "f1")  );
    VERIFY_ERR_CHECK(  SG_zip__write(pCtx, pzip, (SG_byte*) FILE1_CONTENTS, (SG_uint32) (1 + strlen(FILE1_CONTENTS)))  );
    VERIFY_ERR_CHECK(  SG_zip__end_file(pCtx, pzip)  );

#define FILE2_CONTENTS "this is a test of the emergency broadcast system"
    VERIFY_ERR_CHECK(  SG_zip__begin_file(pCtx, pzip, "f2")  );
    VERIFY_ERR_CHECK(  SG_zip__write(pCtx, pzip, (SG_byte*) FILE2_CONTENTS, (SG_uint32) (1 + strlen(FILE2_CONTENTS)))  );
    VERIFY_ERR_CHECK(  SG_zip__end_file(pCtx, pzip)  );

#define FILE3_CONTENTS "x"
    VERIFY_ERR_CHECK(  SG_zip__begin_file(pCtx, pzip, "f3")  );
    VERIFY_ERR_CHECK(  SG_zip__write(pCtx, pzip, (SG_byte*) FILE3_CONTENTS, (SG_uint32) (1 + strlen(FILE3_CONTENTS)))  );
    VERIFY_ERR_CHECK(  SG_zip__end_file(pCtx, pzip)  );

#define FILE4_CONTENTS "spain"
    VERIFY_ERR_CHECK(  SG_zip__begin_file(pCtx, pzip, "f4")  );
    VERIFY_ERR_CHECK(  SG_zip__write(pCtx, pzip, (SG_byte*) FILE4_CONTENTS, (SG_uint32) (1 + strlen(FILE4_CONTENTS)))  );
    VERIFY_ERR_CHECK(  SG_zip__end_file(pCtx, pzip)  );

    VERIFY_ERR_CHECK(  SG_zip__nullclose(pCtx, &pzip)  );

    /* ---------------------------------------------------------------- */
    /* Read the zip file */
    /* ---------------------------------------------------------------- */
    VERIFY_ERR_CHECK(  SG_unzip__open(pCtx, pPath, &punzip)  );

    count = 0;
    b = SG_FALSE;

    VERIFY_ERR_CHECK(  SG_unzip__goto_first_file(pCtx, punzip, &b, NULL, NULL)  );
    while (b)
    {
        count++;
        VERIFY_ERR_CHECK(  SG_unzip__goto_next_file(pCtx, punzip, &b, NULL, NULL)  );
    }
    VERIFY_COND("count", (4 == count));

    b = SG_FALSE;
    VERIFY_ERR_CHECK(  SG_unzip__goto_first_file(pCtx, punzip, &b, &psz_name, &iLen)  );
    VERIFY_COND("b", b);
    VERIFY_COND("name", (0 == strcmp(psz_name, "f1")));
    VERIFY_COND("len", (iLen == (1 + strlen(FILE1_CONTENTS))));

    b = SG_FALSE;
    VERIFY_ERR_CHECK(  SG_unzip__goto_next_file(pCtx, punzip, &b, &psz_name, &iLen)  );
    VERIFY_COND("b", b);
    VERIFY_COND("name", (0 == strcmp(psz_name, "f2")));
    VERIFY_COND("len", (iLen == (1 + strlen(FILE2_CONTENTS))));

    b = SG_FALSE;
    VERIFY_ERR_CHECK(  SG_unzip__goto_next_file(pCtx, punzip, &b, &psz_name, &iLen)  );
    VERIFY_COND("b", b);
    VERIFY_COND("name", (0 == strcmp(psz_name, "f3")));
    VERIFY_COND("len", (iLen == (1 + strlen(FILE3_CONTENTS))));

    b = SG_FALSE;
    VERIFY_ERR_CHECK(  SG_unzip__goto_next_file(pCtx, punzip, &b, &psz_name, &iLen)  );
    VERIFY_COND("b", b);
    VERIFY_COND("name", (0 == strcmp(psz_name, "f4")));
    VERIFY_COND("len", (iLen == (1 + strlen(FILE4_CONTENTS))));

    /* verify that locate_file works */
    VERIFY_ERR_CHECK(  SG_unzip__locate_file(pCtx, punzip, "f2", &b, &iLen)  );
    VERIFY_COND("b", b);
    VERIFY_COND("len", (iLen == (1 + strlen(FILE2_CONTENTS))));
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__open(pCtx, punzip)  );
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__read(pCtx, punzip, buf, sizeof(buf), &iBytesRead)  );
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__close(pCtx, punzip)  );
    VERIFY_COND("len", (iLen == iBytesRead));
    VERIFY_COND("match", (0 == strcmp((char*) buf, FILE2_CONTENTS)));

    /* verify that locate_file does not disturb things when it fails */
    VERIFY_ERR_CHECK(  SG_unzip__locate_file(pCtx, punzip, "not there", &b, &iLen)  );
    VERIFY_COND("b", !b);
    memset(buf, 0, 20);
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__open(pCtx, punzip)  );
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__read(pCtx, punzip, buf, sizeof(buf), &iBytesRead)  );
    VERIFY_ERR_CHECK(  SG_unzip__currentfile__close(pCtx, punzip)  );
    VERIFY_COND("len", ((1 + strlen(FILE2_CONTENTS)) == iBytesRead));
    VERIFY_COND("match", (0 == strcmp((char*) buf, FILE2_CONTENTS)));

    VERIFY_ERR_CHECK(  SG_unzip__nullclose(pCtx, &punzip)  );

    SG_PATHNAME_NULLFREE(pCtx, pPath);

    return;
fail:
    SG_ERR_IGNORE( SG_unzip__nullclose(pCtx, &punzip)  );
    SG_PATHNAME_NULLFREE(pCtx, pPath);
}
/**
 * Import a raw string (probably as the user typed it) and
 * transform it into a repo-path.  And scrub it as appropriate.
 *
 * This routine is inside WC and takes a "pDb" because we need
 * to be able to interpret a null or relative path and convert
 * them into a wd-root-based current/live repo-path.
 *
 * But we also need to be able to call it for arbitrary-cset-based
 * repo-paths that when we don't have a WD.
 *
 * We return both the observed/computed repo-path and the
 * observed/computed repo-path-domain.  The returned repo-path
 * will contain the repo-path-domain so that they are always
 * in normal form.
 *
 * It is up to the caller to decide whether the domain is
 * valid for their purposes and/or throw.
 *
 */
void sg_wc_db__path__anything_to_repopath(SG_context * pCtx,
										  const sg_wc_db * pDb,
										  const char * pszInput,
										  sg_wc_db__path__import_flags flags,
										  SG_string ** ppStringRepoPath,
										  char * pcDomain)
{
	SG_pathname * pPathTemp = NULL;
	SG_string * pStringTemp = NULL;
	SG_bool bValid;

	if (!pszInput || !*pszInput)	// when null, assume either CWD or ROOT.
	{
		switch (flags)
		{
		default:
		case SG_WC_DB__PATH__IMPORT_FLAGS__TREAT_NULL_AS_ERROR:
			SG_ERR_THROW_RETURN(  SG_ERR_INVALIDARG  );

		case SG_WC_DB__PATH__IMPORT_FLAGS__TREAT_NULL_AS_ROOT:
			SG_ERR_CHECK(  SG_PATHNAME__ALLOC__COPY(pCtx, &pPathTemp, pDb->pPathWorkingDirectoryTop)  );
			SG_ERR_CHECK(  sg_wc_db__path__absolute_to_repopath(pCtx, pDb, pPathTemp, ppStringRepoPath)  );
			SG_PATHNAME_NULLFREE(pCtx, pPathTemp);
			*pcDomain = SG_WC__REPO_PATH_DOMAIN__LIVE;
			return;

		case SG_WC_DB__PATH__IMPORT_FLAGS__TREAT_NULL_AS_CWD:
			SG_ERR_CHECK(  SG_PATHNAME__ALLOC(pCtx, &pPathTemp)  );
			SG_ERR_CHECK(  SG_pathname__set__from_cwd(pCtx, pPathTemp)  );
			SG_ERR_CHECK(  sg_wc_db__path__absolute_to_repopath(pCtx, pDb, pPathTemp, ppStringRepoPath)  );
			SG_PATHNAME_NULLFREE(pCtx, pPathTemp);
			*pcDomain = SG_WC__REPO_PATH_DOMAIN__LIVE;
			return;
		}
	}

	if (pszInput[0] != '@')			// a non-repo pathname
	{
		SG_bool bPathIsRelative = SG_FALSE;
		SG_ERR_CHECK(  SG_pathname__is_relative(pCtx, pszInput, &bPathIsRelative)  );
		if (bPathIsRelative)
			SG_ERR_CHECK(  _check_if_relative_paths_allowed(pCtx, pDb)  );

		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__SZ(pCtx, &pPathTemp, pszInput)  );
		SG_ERR_CHECK(  sg_wc_db__path__absolute_to_repopath(pCtx, pDb, pPathTemp, ppStringRepoPath)  );
		SG_PATHNAME_NULLFREE(pCtx, pPathTemp);
		*pcDomain = SG_WC__REPO_PATH_DOMAIN__LIVE;
		return;
	}

	// if they gave us something that started with a "@" we
	// either return it as is or throw if we can't parse it.
	// this ensures that any error messages don't leave the
	// domain out of the repo-path.

	switch (pszInput[1])
	{
	case 0:
		SG_ERR_THROW2_RETURN(  SG_ERR_INVALIDARG,
							   (pCtx, "The input '%s' is not a valid repo-path input.", pszInput)  );

	case SG_WC__REPO_PATH_DOMAIN__G:		// domain "@g..." is a GID and not a path.
		// A '@g' domain input should look like
		// "@gae9ce8e7eaf04b58aef9470b439329f32249aae2358511e1b77b002500da2b78"
		// That is, the 'g' domain specifier is shared with the 'g' in the
		// full GID.  For now a full GID is required; we don't try to do the
		// unique prefix trick like we do for CSET HIDs in a REV-SPEC.  We
		// may think about adding that later.

		SG_ERR_CHECK(  SG_gid__verify_format(pCtx, &pszInput[1], &bValid)  );
		if (!bValid)
			SG_ERR_THROW2(  SG_ERR_INVALIDARG,
							(pCtx, "The input '%s' is not a valid gid-domain input.", pszInput)  );
		SG_ERR_CHECK(  SG_STRING__ALLOC__SZ(pCtx, ppStringRepoPath, pszInput)  );
		*pcDomain = SG_WC__REPO_PATH_DOMAIN__G;
		return;

	case SG_WC__REPO_PATH_DOMAIN__T:		// domain "@t..." is a temporary GID and not a path.
		// A '@t' domain input should look like
		// "@tae9ce8e7eaf04b58aef9470b439329f32249aae2358511e1b77b002500da2b78"
		// That is, the 't' domain specifier replaces the normal 'g' in the
		// full GID.  For now a full GID is required; we don't try to do the
		// unique prefix trick like we do for CSET HIDs in a REV-SPEC.  We
		// may think about adding that later.  We use a 't' when reporting
		// STATUS rather than a 'g' as a reminder that the ID is only valid
		// until the end of the transaction.
		//
		// make a g-version of the string so we can validate it.
		// but still return the t-version.

		SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pStringTemp)  );
		SG_ERR_CHECK(  SG_string__sprintf(pCtx, pStringTemp, "%c%s",
										  SG_WC__REPO_PATH_DOMAIN__G,
										  &pszInput[2])  );
		SG_ERR_CHECK(  SG_gid__verify_format(pCtx, SG_string__sz(pStringTemp), &bValid)  );
		SG_STRING_NULLFREE(pCtx, pStringTemp);
		if (!bValid)
			SG_ERR_THROW2(  SG_ERR_INVALIDARG,
							(pCtx, "The input '%s' is not a valid temp-gid-domain input.", pszInput)  );
		SG_ERR_CHECK(  SG_STRING__ALLOC__SZ(pCtx, ppStringRepoPath, pszInput)  );
		*pcDomain = SG_WC__REPO_PATH_DOMAIN__T;
		return;

	case SG_WC__REPO_PATH_DOMAIN__LIVE:		// domain "@/foo..." is a normal current/live repo-path
		SG_ERR_CHECK(  _complain_if_unnormalized(pCtx, &pszInput[1])  );
		SG_ERR_CHECK(  SG_STRING__ALLOC__SZ(pCtx, ppStringRepoPath, pszInput)  );
		*pcDomain = SG_WC__REPO_PATH_DOMAIN__LIVE;
		return;

	default:		// we allow any other SINGLE character to be a domain.
		if (pszInput[2] != '/')
			SG_ERR_THROW2_RETURN(  SG_ERR_INVALIDARG,
								   (pCtx, "The input '%s' is not a valid repo-path input.", pszInput)  );

		// we have "@x/foo...." for some character x.
		SG_ERR_CHECK(  _complain_if_unnormalized(pCtx, &pszInput[2])  );
		SG_ERR_CHECK(  SG_STRING__ALLOC__SZ(pCtx, ppStringRepoPath, pszInput)  );
		*pcDomain = pszInput[1];
		return;
	}

fail:
	SG_PATHNAME_NULLFREE(pCtx, pPathTemp);
	SG_STRING_NULLFREE(pCtx, pStringTemp);
}
Beispiel #15
0
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;
}