Пример #1
0
void SG_localsettings__update__varray(SG_context * pCtx, const char * psz_path, const SG_varray * pValue)
{
	SG_jsondb* p = NULL;
    SG_string* pstr_path = NULL;

    SG_ASSERT(pCtx);
    SG_NONEMPTYCHECK_RETURN(psz_path);
    SG_NULLARGCHECK_RETURN(pValue);

    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path)  );
    if ('/' == psz_path[0])
    {
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s", psz_path)  );
    }
    else
    {
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s", SG_LOCALSETTING__SCOPE__MACHINE, psz_path)  );
    }

    SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );

	SG_ERR_CHECK(  SG_jsondb__update__varray(pCtx, p, SG_string__sz(pstr_path), SG_TRUE, pValue)  );

fail:
	SG_JSONDB_NULLFREE(pCtx, p);
    SG_STRING_NULLFREE(pCtx, pstr_path);
}
Пример #2
0
void SG_getopt__print_option(SG_context* pCtx, SG_console_stream cs, SG_getopt_option* opt, const char * overrideDesc)
{
	SG_string *opts;

	if (opt == NULL)
    {
		SG_ERR_IGNORE(  SG_console(pCtx, cs, "?")  );
		return;
    }

	SG_ERR_CHECK(  SG_string__alloc(pCtx, &opts)  );

	/* We have a valid option which may or may not have a "short
		name" (a single-character alias for the long option). */
	if (opt->optch <= 255)
		SG_ERR_CHECK(  SG_string__sprintf(pCtx, opts, "-%c [--%s]", opt->optch, opt->pStringName)  );
	else
		SG_ERR_CHECK(  SG_string__sprintf(pCtx, opts, "--%s", opt->pStringName)  );

	if (opt->has_arg)
		SG_ERR_CHECK(  SG_string__append__sz(pCtx, opts, " ARG")  );

	if (overrideDesc)
		SG_ERR_IGNORE(  SG_console(pCtx, cs, "%-20s :  %s\n", SG_string__sz(opts), overrideDesc)  );
	else
		SG_ERR_IGNORE(  SG_console(pCtx, cs, "%-20s :  %s\n", SG_string__sz(opts), opt->pStringDescription)  );


fail:
	SG_STRING_NULLFREE(pCtx, opts);
}
Пример #3
0
void SG_localsettings__varray__append(SG_context * pCtx, const char* psz_path, const char* pValue)
{
	SG_jsondb* p = NULL;
    SG_string* pstr = NULL;
    SG_varray* pva = NULL;
    SG_string* pstr_path_found = NULL;

	SG_ASSERT(pCtx);
	SG_NONEMPTYCHECK_RETURN(psz_path);

    SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );
    SG_ERR_CHECK(  SG_localsettings__get__varray(pCtx, psz_path, NULL, &pva, &pstr_path_found)  );
    if (!pstr_path_found)
    {
        // this came from factory defaults.
        SG_ERR_CHECK(  SG_string__alloc(pCtx, &pstr_path_found)  );
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path_found, "%s/%s", SG_LOCALSETTING__SCOPE__MACHINE, psz_path)  );
        SG_ERR_CHECK(  SG_localsettings__update__varray(pCtx, SG_string__sz(pstr_path_found), pva)  );
    }

    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr)  );
    SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr, "%s/#", SG_string__sz(pstr_path_found))  );
	SG_ERR_CHECK(  SG_jsondb__update__string__sz(pCtx, p, SG_string__sz(pstr), SG_TRUE, pValue)  );

fail:
    SG_STRING_NULLFREE(pCtx, pstr);
	SG_JSONDB_NULLFREE(pCtx, p);
    SG_VARRAY_NULLFREE(pCtx, pva);
    SG_STRING_NULLFREE(pCtx, pstr_path_found);
}
Пример #4
0
void SG_localsettings__reset(SG_context * pCtx, const char* psz_path)
{
    SG_jsondb* p = NULL;
    SG_string* pstr_path = NULL;

    SG_ASSERT(pCtx);
    SG_NONEMPTYCHECK_RETURN(psz_path);

    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path)  );
    if ('/' == psz_path[0])
    {
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s", psz_path)  );
    }
    else
    {
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s", SG_LOCALSETTING__SCOPE__MACHINE, psz_path)  );
    }

    SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );
	SG_jsondb__remove(pCtx, p, SG_string__sz(pstr_path));
    SG_ERR_CHECK_CURRENT_DISREGARD(SG_ERR_NOT_FOUND);

fail:
	SG_JSONDB_NULLFREE(pCtx, p);
    SG_STRING_NULLFREE(pCtx, pstr_path);
}
Пример #5
0
void SG_localsettings__varray__remove_first_match(SG_context * pCtx, const char* psz_path, const char* psz_val)
{
	SG_jsondb* p = NULL;
    SG_string* pstr_path_element = NULL;
    SG_varray* pva = NULL;
    SG_uint32 ndx = 0;
    SG_uint32 count = 0;
    SG_uint32 i = 0;
    SG_bool b_found = SG_FALSE;
    SG_string* pstr_path_found = NULL;

	SG_ASSERT(pCtx);
	SG_NONEMPTYCHECK_RETURN(psz_path);

    SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );
    SG_ERR_CHECK(  SG_localsettings__get__varray(pCtx, psz_path, NULL, &pva, &pstr_path_found)  );
    if (pva)
    {
        if (!pstr_path_found)
        {
            // this came from factory defaults.
            SG_ERR_CHECK(  SG_string__alloc(pCtx, &pstr_path_found)  );
            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path_found, "%s/%s", SG_LOCALSETTING__SCOPE__MACHINE, psz_path)  );
            SG_ERR_CHECK(  SG_localsettings__update__varray(pCtx, SG_string__sz(pstr_path_found), pva)  );
        }

        SG_ERR_CHECK(  SG_varray__count(pCtx, pva, &count)  );
        for (i=0; i<count; i++)
        {
            const char* psz = NULL;

            SG_ERR_CHECK(  SG_varray__get__sz(pCtx, pva, i, &psz)  );
            if (0 == strcmp(psz, psz_val))
            {
                b_found = SG_TRUE;
                ndx = i;
                break;
            }
        }
        if (b_found)
        {
            SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path_element)  );
            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path_element, "%s/%d", SG_string__sz(pstr_path_found), ndx)  );
            SG_ERR_CHECK(  SG_jsondb__remove(pCtx, p, SG_string__sz(pstr_path_element))  );
        }
    }

fail:
    SG_VARRAY_NULLFREE(pCtx, pva);
    SG_STRING_NULLFREE(pCtx, pstr_path_found);
    SG_STRING_NULLFREE(pCtx, pstr_path_element);
	SG_JSONDB_NULLFREE(pCtx, p);
}
Пример #6
0
/**
 * Create a label for one side of a UNIFIED DIFF.  This will appear on one of
 * the header lines after the "+++ " or "--- ".  (We DO NOT create the "+++ "
 * portion.)
 *
 * Gnu-diff (when --label is not used) creates something like:
 *      +++ %s\t%s		with the file's relative pathname and date-time-modified.
 *
 *      --- d1/date2	1970-01-01 00:00:00.000000000 +0000
 *      +++ d2/date2	2009-04-30 13:10:57.000000000 +0000
 *
 * BZR's diff command creates something like:
 *
 *      --- d2/date2	2009-04-30 12:38:41 +0000
 *      +++ d2/date2	2009-04-30 13:10:57 +0000
 *
 * GIT's diff command creates something like:
 *
 *      --- a/eeeeee.txt
 *      +++ b/eeeeee.txt
 *
 * So, we can pretty much do whatever we want here.
 *
 * I'm going to try the following and see if we like it:
 * [] for a historical version, print:
 *      +++ %s\t%s    with the repo-path and the HID.
 *
 *    we don't have a valid date-stamp to print. (our caller might have
 *    the date-stamp on the changeset, but that doesn't have anything to
 *    to with the date on an indivdual file (the file might not have even
 *    been modified in that changeset).
 *
 *    the HID may be useful later.
 *
 * [] for a working-directory version, print:
 *      +++ %s\t%s    with the repo-path and the live date-time-stamp.
 *
 *    since the file is in the working-directory, the date stamp has
 *    some validity (it doesn't mean that they changed the file or reflect
 *    the last change (it could be date of the last get-latest for all we
 *    know)).
 *
 * [] just for sanity, we allow a repo-path only version:
 *      +++ %s
 *
 * In all cases we print the complete repo-path "@/a/b/c/foo.c".
 * The repo-path is as computed in SG_treediff2 and reflects all pathname
 * renames/moves.
 *
 * TODO do we care about feeding this output to PATCH and how it digests
 * pathnames and with the various -p0 -p1 ... arguments?
 *
 * We return a string that you must free.
 */
void SG_diff_utils__make_label(SG_context * pCtx,
							   const char * szRepoPath,
							   const char * szHid,
							   const char * szDate,
							   SG_string ** ppStringLabel)
{
	SG_string * pString = NULL;

	SG_NONEMPTYCHECK_RETURN(szRepoPath);

	if (szHid && szDate)			// allow zero or one, but not both
		SG_ERR_THROW_RETURN(  SG_ERR_INVALIDARG  );

	SG_NULLARGCHECK(ppStringLabel);

	SG_ERR_CHECK_RETURN(  SG_STRING__ALLOC(pCtx,&pString)  );

	//////////////////////////////////////////////////////////////////
	// WARNING: All of the input arguments are in our internal NFC UTF-8 format
	// WARNING: (as is everything).  SG_exec__() will convert whatever we construct
	// WARNING: here to an os-buffer (utf-8, locale, or wchar_t) before giving it
	// WARNING: to execvp() or CreateProcessW().
	// WARNING:
	// WARNING: I *think* this is what we want.
	// WARNING:
	// WARNING: We can't be sure how the child process will handle the label text
	// WARNING: when it prints it to its STDOUT.  This may cause some confusion.
	// WARNING: For example, NFC/NFD issues on MAC or some '?' characters getting
	// WARNING: printed by cygwin's version of gnu-diff and etc.
	// WARNING:
	// WARNING: I don't know if there are actually any issues here or not or if
	// WARNING: so whether they will cause a problem.
	//////////////////////////////////////////////////////////////////

	if (szHid)
		SG_ERR_CHECK(  SG_string__sprintf(pCtx,
										  pString,"%s\t%s",
										  szRepoPath,szHid)  );
	else if (szDate)
		SG_ERR_CHECK(  SG_string__sprintf(pCtx,
										  pString,"%s\t%s",
										  szRepoPath,szDate)  );
	else
		SG_ERR_CHECK(  SG_string__set__sz(pCtx,pString,szRepoPath)  );

	*ppStringLabel = pString;

	return;

fail:
	SG_STRING_NULLFREE(pCtx, pString);
}
/**
 * Create a pathname in the per-file temp-dir for one
 * version of the file.
 *
 * We use the ancestor version of the entryname
 * to avoid issues with pending renames.
 * 
 */
void _sg_mrg__create_pathname_for_conflict_file(SG_context * pCtx,
												SG_mrg * pMrg,
												SG_mrg_cset_entry_conflict * pMrgCSetEntryConflict,
												const char * pszPrefix,
												SG_pathname ** ppPathReturned)
{
	SG_pathname * pPath = NULL;
	SG_string * pString = NULL;

	SG_ERR_CHECK(  _sg_mrg__ensure_temp_dir_for_file_conflict(pCtx, pMrg, pMrgCSetEntryConflict)  );

	// create something like: "<sgtemp>/<gid7>_YYYYMMDD_<k>/<prefix>~<entryname>"

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pString)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, pString, "%s~%s",
									  pszPrefix,
									  SG_string__sz(pMrgCSetEntryConflict->pMrgCSetEntry_Ancestor->pStringEntryname))  );
	SG_ERR_CHECK(  SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPath,
												   pMrgCSetEntryConflict->pPathTempDirForFile,
												   SG_string__sz(pString))  );

	SG_STRING_NULLFREE(pCtx, pString);
	*ppPathReturned = pPath;
	return;

fail:
	SG_STRING_NULLFREE(pCtx, pString);
	SG_PATHNAME_NULLFREE(pCtx, pPath);
}
Пример #8
0
void SG_sync__remember_sync_target(SG_context* pCtx, const char * pszLocalRepoDescriptor, const char * pszSyncTarget)
{
	SG_string * pString = NULL;
	SG_varray * pva_targets = NULL;
	SG_bool bFound = SG_FALSE;
	SG_uint32 nEntry = 0;

	//Save this destination to the local setting of previously used destinations.
	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pString)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, pString, "%s/%s/%s",
									SG_LOCALSETTING__SCOPE__INSTANCE,
									pszLocalRepoDescriptor,
									SG_LOCALSETTING__SYNC_TARGETS)  );
	SG_ERR_CHECK(  SG_localsettings__get__varray(pCtx, SG_string__sz(pString), NULL, &pva_targets, NULL)  );
	if (pva_targets)
		SG_ERR_CHECK(  SG_varray__find__sz(pCtx, pva_targets, pszSyncTarget, &bFound, &nEntry)  );
	else
		SG_VARRAY__ALLOC(pCtx, &pva_targets);
	if (!bFound)
	{
		SG_ERR_CHECK(  SG_varray__append__string__sz(pCtx, pva_targets, pszSyncTarget)  );
		SG_ERR_CHECK(  SG_localsettings__update__varray(pCtx, SG_string__sz(pString), pva_targets)  );
	}
fail:
	SG_STRING_NULLFREE(pCtx, pString);
	SG_VARRAY_NULLFREE(pCtx, pva_targets);
}
Пример #9
0
void SG_localsettings__descriptor__update__sz(
	SG_context * pCtx,
	const char * psz_descriptor_name,
	const char * psz_path,
	const char * pValue)
{
	SG_jsondb* p = NULL;
	SG_string* pstr_path = NULL;

	SG_ASSERT(pCtx);
	SG_NONEMPTYCHECK_RETURN(psz_descriptor_name);
	SG_NONEMPTYCHECK_RETURN(psz_path);
	SG_ARGCHECK_RETURN('/' != psz_path[0], psz_path);

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s/%s",
		SG_LOCALSETTING__SCOPE__INSTANCE, psz_descriptor_name, psz_path)  );

	SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );
	SG_ERR_CHECK(  SG_jsondb__update__string__sz(pCtx, p, SG_string__sz(pstr_path), SG_TRUE, pValue)  );

fail:
	SG_STRING_NULLFREE(pCtx, pstr_path);
	SG_JSONDB_NULLFREE(pCtx, p);
}
Пример #10
0
void SG_workingdir__generate_and_create_temp_dir_for_purpose(SG_context * pCtx,
															 const SG_pathname * pPathWorkingDirectoryTop,
															 const char * pszPurpose,
															 SG_pathname ** ppPathTempDir)
{
	SG_pathname * pPathTempRoot = NULL;
	SG_pathname * pPath = NULL;
	SG_string * pString = NULL;
	SG_int64 iTimeUTC;
	SG_time tmLocal;
	SG_uint32 kAttempt = 0;

	SG_NONEMPTYCHECK_RETURN(pszPurpose);
	SG_NULLARGCHECK_RETURN(ppPathTempDir);

	// get path to "<wd-top>/.sgtemp".
	SG_ERR_CHECK(  SG_workingdir__get_temp_path(pCtx,pPathWorkingDirectoryTop,&pPathTempRoot)  );

	SG_ERR_CHECK(  SG_time__get_milliseconds_since_1970_utc(pCtx,&iTimeUTC)  );
	SG_ERR_CHECK(  SG_time__decode__local(pCtx,iTimeUTC,&tmLocal)  );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx,&pString)  );

	while (1)
	{
		// build path "<wd-top>/.sgtemp/<purpose>_20091201_0".
		// where <purpose> is something like "revert" or "merge".

		SG_ERR_CHECK(  SG_string__sprintf(pCtx,pString,"%s_%04d%02d%02d_%d",
										  pszPurpose,
										  tmLocal.year,tmLocal.month,tmLocal.mday,
										  kAttempt++)  );
		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx,&pPath,pPathTempRoot,SG_string__sz(pString))  );

		// try to create a NEW temp directory.  if this path already exists on disk,
		// loop and try again.  if we have a hard errors, just give up.

		SG_fsobj__mkdir_recursive__pathname(pCtx,pPath);
		if (SG_context__has_err(pCtx) == SG_FALSE)
			goto success;

		if (SG_context__err_equals(pCtx,SG_ERR_DIR_ALREADY_EXISTS) == SG_FALSE)
			SG_ERR_RETHROW;

		SG_context__err_reset(pCtx);
		SG_PATHNAME_NULLFREE(pCtx,pPath);
	}

success:
	*ppPathTempDir = pPath;

	SG_STRING_NULLFREE(pCtx, pString);
	SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot);
	return;

fail:
	SG_STRING_NULLFREE(pCtx, pString);
	SG_PATHNAME_NULLFREE(pCtx, pPathTempRoot);
	SG_PATHNAME_NULLFREE(pCtx, pPath);
}
Пример #11
0
void SG_user__set_user__repo(
	SG_context* pCtx,
    SG_repo* pRepo,
    const char* psz_email
    )
{
    SG_vhash* pvh_user = NULL;
    char* psz_admin_id = NULL;
    const char* psz_userid = NULL;
    SG_string* pstr_path = NULL;

    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path)  );

    if (pRepo)
    {
        SG_ERR_CHECK(  SG_user__lookup_by_email(pCtx, pRepo, psz_email, &pvh_user)  );
        if (!pvh_user)
        {
            SG_ERR_THROW(  SG_ERR_USER_NOT_FOUND  );
        }

        SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, pvh_user, SG_ZING_FIELD__RECID, &psz_userid)  );
        SG_ERR_CHECK(  SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id)  );

        // we store this userid under the admin scope of the repo we were given
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s/%s",
                    SG_LOCALSETTING__SCOPE__ADMIN,
                    psz_admin_id,
                    SG_LOCALSETTING__USERID
                    )  );
        SG_ERR_CHECK(  SG_localsettings__update__sz(pCtx, SG_string__sz(pstr_path), psz_userid)  );
    }

    // AND we store this email address in machine scope for fallback lookups
    SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s",
                SG_LOCALSETTING__SCOPE__MACHINE,
                SG_LOCALSETTING__USEREMAIL
                )  );
    SG_ERR_CHECK(  SG_localsettings__update__sz(pCtx, SG_string__sz(pstr_path), psz_email)  );

fail:
    SG_STRING_NULLFREE(pCtx, pstr_path);
    SG_NULLFREE(pCtx, psz_admin_id);
    SG_VHASH_NULLFREE(pCtx, pvh_user);
}
/**
 * Convert an alias into a domain-specific repo-path
 * relative to this cset.  This is based *STRICTLY*
 * upon the content of this tne_* table.  We DO NOT
 * know anything about pending changes or the tbl_pc
 * table.
 *
 * We also DO NOT know anything about the association
 * of domain and which tne_* table to use; that is the
 * responsibility of the caller.
 *
 * For example, it is usually the case that we have the
 * domain mapping:
 *     'b' ==> "L0"
 *     'c' ==> "L1"
 * but we don't assume that.
 *
 */
void sg_wc_db__tne__get_extended_repo_path_from_alias(SG_context * pCtx,
													  sg_wc_db * pDb,
													  const sg_wc_db__cset_row * pCSetRow,
													  SG_uint64 uiAliasGid,
													  char chDomain,
													  SG_string ** ppStringRepoPath)
{
	SG_string * pStringRepoPath = NULL;
	sg_wc_db__tne_row * pTneRow = NULL;

	SG_NULLARGCHECK_RETURN( pDb );
	SG_NULLARGCHECK_RETURN( pCSetRow );
	SG_ARGCHECK_RETURN( (strchr(("abcdef"        // 'g' is reserved
								 "hijklmnopqrs"  // 't' is reserved
								 "uvwxyz"        // '/' is reserved
								 "0123456789"),
								chDomain)), chDomain );
	SG_NULLARGCHECK_RETURN( ppStringRepoPath );

	SG_ERR_CHECK(  sg_wc_db__tne__get_row_by_alias(pCtx, pDb, pCSetRow,
												   uiAliasGid,
												   NULL, &pTneRow)  );
	SG_ASSERT(  (pTneRow)  );

	if (pTneRow->p_s->uiAliasGidParent == SG_WC_DB__ALIAS_GID__NULL_ROOT)
	{
		SG_ASSERT_RELEASE_FAIL( (strcmp(pTneRow->p_s->pszEntryname, "@")==0) );

		SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pStringRepoPath)  );
		SG_ERR_CHECK(  SG_string__sprintf(pCtx, pStringRepoPath, "@%c/", chDomain)  );
	}
	else
	{
		SG_ERR_CHECK(  sg_wc_db__tne__get_extended_repo_path_from_alias(pCtx, pDb, pCSetRow,
																		pTneRow->p_s->uiAliasGidParent,
																		chDomain,
																		&pStringRepoPath)  );
		SG_ASSERT( pStringRepoPath );
		SG_ERR_CHECK(  SG_repopath__append_entryname(pCtx, pStringRepoPath,
													 pTneRow->p_s->pszEntryname,
													 (pTneRow->p_s->tneType == SG_TREENODEENTRY_TYPE_DIRECTORY))  );
	}
	
	*ppStringRepoPath = pStringRepoPath;
	pStringRepoPath = NULL;

fail:
	SG_WC_DB__TNE_ROW__NULLFREE(pCtx, pTneRow);
	SG_STRING_NULLFREE(pCtx, pStringRepoPath);
}
Пример #13
0
void MyFn(test__formatRfc850)(SG_context *pCtx)
{
	const char *expected = "Tue, 16 Mar 2010 14:11:13 GMT";
	SG_int32 epoch = 1268748673;
	SG_int64 sgtime = (SG_int64)epoch * 1000;
	SG_string *msg = NULL;
	char formatted[1024];

	SG_ERR_CHECK(  SG_time__formatRFC850(pCtx, sgtime, formatted, sizeof(formatted))  );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &msg)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, msg, "formatting '%lli': expected '%s', got '%s'", sgtime, expected, formatted)  );

	VERIFY_COND(SG_string__sz(msg), strcmp(expected, formatted) == 0);

fail:
	SG_STRING_NULLFREE(pCtx, msg);
}
Пример #14
0
void MyFn(test__parseRfc850)(SG_context *pCtx)
{
	const char *ims = "Tue, 16 Mar 2010 14:11:13 GMT";
	SG_int32 epoch = 1268748673;
	SG_int64 sgtime = (SG_int64)epoch * 1000;
	SG_string *msg = NULL;
	SG_int64 parsed = 0, localparsed;

	SG_ERR_CHECK(  SG_time__parseRFC850(pCtx, ims, &parsed, &localparsed)  );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &msg)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, msg, "parsing '%s': expected '%lli', got '%lli'", ims, (long long)sgtime, (long long)parsed)  );

	VERIFY_COND(SG_string__sz(msg), parsed == sgtime);

fail:
	SG_STRING_NULLFREE(pCtx, msg);
}
/**
 * Convert simple GID into a gid-domain repo-path.
 *
 */
void sg_wc_db__path__gid_to_gid_repopath(SG_context * pCtx,
										 const char * pszGid,
										 SG_string ** ppStringGidRepoPath)
{
	SG_string * pString = NULL;

	SG_NONEMPTYCHECK_RETURN( pszGid );
	SG_NULLARGCHECK_RETURN( ppStringGidRepoPath );

	SG_ARGCHECK_RETURN( ((pszGid[0] == 'g') || (pszGid[0] == 't')), pszGid );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pString)  );
	SG_ERR_CHECK(  SG_string__sprintf(pCtx, pString, "@%s", pszGid)  );

	*ppStringGidRepoPath = pString;
	return;

fail:
	SG_STRING_NULLFREE(pCtx, pString);
}
void sg_wc_db__path__generate_backup_path(SG_context * pCtx,
										  const sg_wc_db * pDb,
										  const char * pszGid,
										  const char * pszEntryname,
										  SG_pathname ** ppPathBackup)
{
	SG_pathname * pPath = NULL;
	SG_string * pString = NULL;
	SG_uint32 k = 0;
	SG_bool bExists;

	// TODO 2011/10/25 assert no slashes in entryname.

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pString)  );
	for (k=0; k<100; k++)
	{
		SG_ERR_CHECK(  SG_string__clear(pCtx, pString)  );
		
		SG_ERR_CHECK(  SG_string__sprintf(pCtx, pString, SG_BACKUP_FORMAT, pszGid, pszEntryname, k)  );
		SG_ERR_CHECK(  SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &pPath, pDb->pPathWorkingDirectoryTop, SG_string__sz(pString))  );

		SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx, pPath, &bExists, NULL, NULL)  );
		if (!bExists)
			break;

		SG_PATHNAME_NULLFREE(pCtx, pPath);
	}

	if (k == 100)
	{
        SG_ERR_THROW2(  SG_ERR_TOO_MANY_BACKUP_FILES, (pCtx, "%s", pszEntryname)  );
	}

	*ppPathBackup = pPath;
	pPath = NULL;

fail:
	SG_PATHNAME_NULLFREE(pCtx, pPath);
	SG_STRING_NULLFREE(pCtx, pString);
}
/**
 * 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);
}
/**
 * Our caller is trying to create new repo and create a WD
 * mapped to it.  The destination directory may or may not
 * have already existed on disk before we started.  If we are
 * building upon an existing directory, verify that it doesn't
 * contain any submodules because we don't yet support them.
 *
 */
static void _check_for_nested_drawer(SG_context * pCtx,
                                     SG_wc_tx * pWcTx)
{
    SG_varray * pvaStatus = NULL;
    SG_string * pString_MyDrawerRepoPath = NULL;
    SG_string * pString_MatchedRepoPath = NULL;
    const char * psz_MyDrawerName = NULL;
    const char * psz_MyDrawerRepoPath = NULL;
    SG_uint32 k, nrItems;

    if (pWcTx->bWeCreated_WD || pWcTx->bWeCreated_WD_Contents)
        return;

    SG_ERR_CHECK(  SG_wc_tx__status(pCtx, pWcTx, NULL, SG_UINT32_MAX,
                                    SG_FALSE, // bListUnchanged
                                    SG_TRUE,  // bNoIgnores
                                    SG_TRUE,  // bNoTSC,
                                    SG_FALSE, // bListSparse
                                    SG_TRUE,  // bListReserved
                                    SG_TRUE,  // bNoSort,
                                    &pvaStatus,
                                    NULL)  );
    if (!pvaStatus)
        return;

    // TODO 2012/11/13 For now I'm just going to see if there is a
    // TODO            .sgdrawer somewhere within the directory tree.
    // TODO            In theory, we could have ADD/ADDREMOVE just
    // TODO            look for them and refuse to add its parent
    // TODO            directory, but I don't to even support that
    // TODO            until we've properly dealt with submodules.
    // TODO
    // TODO            So for now, if there is a WD deeply nested within
    // TODO            this directory, we just complain.  This is mainly
    // TODO            to prevent accidents.  (Because they can still
    // TODO            manually move a sub-WD somehere deep into this
    // TODO            directory at some point in the future.)

    SG_ERR_CHECK(  SG_workingdir__get_drawer_directory_name(pCtx, &psz_MyDrawerName)  );
    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pString_MyDrawerRepoPath)  );
    SG_ERR_CHECK(  SG_string__sprintf(pCtx, pString_MyDrawerRepoPath, "@/%s", psz_MyDrawerName)  );
    SG_ERR_CHECK(  SG_repopath__ensure_final_slash(pCtx, pString_MyDrawerRepoPath)  );
    psz_MyDrawerRepoPath = SG_string__sz(pString_MyDrawerRepoPath);

    SG_ERR_CHECK(  SG_varray__count(pCtx, pvaStatus, &nrItems)  );
    for (k=0; k<nrItems; k++)
    {
        SG_vhash * pvhItem;
        SG_vhash * pvhItemStatus;
        SG_bool bIsReserved;
        SG_ERR_CHECK(  SG_varray__get__vhash(pCtx, pvaStatus, k, &pvhItem)  );
        SG_ERR_CHECK(  SG_vhash__get__vhash(pCtx, pvhItem, "status", &pvhItemStatus)  );
        SG_ERR_CHECK(  SG_vhash__has(pCtx, pvhItemStatus, "isReserved", &bIsReserved)  );
        if (bIsReserved)
        {
            // Don't freak out over the .sgdrawer that we just created in the root.
            const char * pszRepoPath;
            SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, pvhItem, "path", &pszRepoPath)  );
            if (strcmp(pszRepoPath, psz_MyDrawerRepoPath) != 0)
            {
                SG_ERR_CHECK(  SG_STRING__ALLOC__SZ(pCtx, &pString_MatchedRepoPath, pszRepoPath)  );
                SG_ERR_CHECK(  SG_repopath__remove_last(pCtx, pString_MatchedRepoPath)  );

                SG_ERR_THROW2(  SG_ERR_ENTRY_ALREADY_UNDER_VERSION_CONTROL,
                                (pCtx, "The directory '%s' contains a working copy and submodules are not yet supported.",
                                 SG_string__sz(pString_MatchedRepoPath))  );
            }
        }
    }

fail:
    SG_STRING_NULLFREE(pCtx, pString_MatchedRepoPath);
    SG_STRING_NULLFREE(pCtx, pString_MyDrawerRepoPath);
    SG_VARRAY_NULLFREE(pCtx, pvaStatus);
}
static void _s2__do_cset_vs_cset(SG_context * pCtx,
                                 const SG_option_state * pOptSt,
                                 const SG_stringarray * psaArgs,
                                 SG_uint32 * pNrErrors)
{
    SG_varray * pvaStatus = NULL;
    SG_varray * pvaStatusDirtyFiles = NULL;
    SG_stringarray * psa1 = NULL;
    SG_string * pStringGidRepoPath = NULL;
    SG_string * pStringErr = NULL;
    SG_uint32 nrErrors = 0;

    SG_ERR_CHECK(  SG_vv2__status(pCtx,
                                  pOptSt->psz_repo,
                                  pOptSt->pRevSpec,
                                  psaArgs,
                                  WC__GET_DEPTH(pOptSt),
                                  SG_FALSE, // bNoSort
                                  &pvaStatus, NULL)  );
    if (pvaStatus)
    {
        if (pOptSt->bInteractive)
        {
            // Filter list down to just modified files and show them one-by-one.
            SG_ERR_CHECK(  _get_dirty_files(pCtx, pvaStatus, &pvaStatusDirtyFiles)  );
            if (pvaStatusDirtyFiles)
                SG_ERR_CHECK(  _do_gui_diffs(pCtx, SG_FALSE, pOptSt, pvaStatusDirtyFiles, &nrErrors)  );
        }
        else
        {
            SG_uint32 k, nrItems;

            // Print the changes with PATCH-like headers.
            // Accumulate any tool errors.
            SG_ERR_CHECK(  SG_varray__count(pCtx, pvaStatus, &nrItems)  );
            for (k=0; k<nrItems; k++)
            {
                SG_vhash * pvhItem;
                const char * pszGid = NULL;

                SG_ERR_CHECK(  SG_varray__get__vhash(pCtx, pvaStatus, k, &pvhItem)  );

                // TODO 2013/02/22 Our pvhItem has all of the details for the diff,
                // TODO            but we don't yet have a public API to let it be
                // TODO            used as is.  So we build a @gid repo-path and
                // TODO            run the old historical diff code on a 1-item array
                // TODO            containing this @gid.
                // TODO
                // TODO            We should fix this to just pass down the pvhItem
                // TOOD            so that it doesn't have to repeat the status lookup.

                SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, pvhItem, "gid", &pszGid)  );
                SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pStringGidRepoPath)  );
                SG_ERR_CHECK(  SG_string__sprintf(pCtx, pStringGidRepoPath, "@%s", pszGid)  );

                SG_ERR_CHECK(  SG_STRINGARRAY__ALLOC(pCtx, &psa1, 1)  );
                SG_ERR_CHECK(  SG_stringarray__add(pCtx, psa1, SG_string__sz(pStringGidRepoPath))  );

                SG_vv2__diff_to_stream__throw(pCtx, pOptSt->psz_repo, pOptSt->pRevSpec,
                                              psa1, 0,
                                              SG_TRUE,		// bNoSort -- doesn't matter only 1 item in list
                                              SG_FALSE,		// bInteractive,
                                              pOptSt->psz_tool);
                // Don't throw the error from the tool.  Just print it on STDERR
                // and remember that we had an error so that don't stop showing
                // the diffs just because we stumble over a changed binary file
                // or mis-configured tool, for example.
                if (SG_context__has_err(pCtx))
                {
                    SG_context__err_to_string(pCtx, SG_FALSE, &pStringErr);
                    SG_context__err_reset(pCtx);
                    SG_ERR_CHECK(  SG_console__raw(pCtx, SG_CS_STDERR, SG_string__sz(pStringErr))  );
                    SG_STRING_NULLFREE(pCtx, pStringErr);

                    nrErrors++;
                }

                SG_STRING_NULLFREE(pCtx, pStringGidRepoPath);
                SG_STRINGARRAY_NULLFREE(pCtx, psa1);
            }
        }
    }

    *pNrErrors = nrErrors;

fail:
    SG_VARRAY_NULLFREE(pCtx, pvaStatus);
    SG_VARRAY_NULLFREE(pCtx, pvaStatusDirtyFiles);
    SG_STRINGARRAY_NULLFREE(pCtx, psa1);
    SG_STRING_NULLFREE(pCtx, pStringGidRepoPath);
    SG_STRING_NULLFREE(pCtx, pStringErr);
}
/**
 * Do diff of an individual item.
 * When WC-based, we have a "DiffStep" vhash.
 * When historical, we have an item from a pvaStatus.
 *
 */
static void _do_diff1(SG_context * pCtx,
                      SG_bool bWC,
                      const SG_option_state * pOptSt,
                      const SG_vhash * pvhItem,
                      SG_uint32 * piResult)
{
    SG_string * pStringGidRepoPath = NULL;
    SG_vhash * pvhResultCodes = NULL;
    SG_stringarray * psa1 = NULL;
    const char * pszGid;
    SG_int64 i64Result = 0;
    SG_string * pStringErr = NULL;

    SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, pvhItem, "gid", &pszGid)  );

    if (bWC)
    {
        SG_pathname * pPathWc = NULL;
        SG_bool bHasTool = SG_FALSE;

        // With the __diff__setup() and __diff__run() changes, we have already
        // examined the items during the __setup() step and recorded a tool for
        // the *FILE* that have changed content.  So if "tool" isn't set in the
        // DiffStep/Item, we don't need to diff it -- it could be a structural
        // change, a non-file, a found item, etc.
        //
        // we do not use SG_wc__diff__throw() because we already have the diff info
        // and we want to control the result-code processing below.

        SG_ERR_CHECK(  SG_vhash__has(pCtx, pvhItem, "tool", &bHasTool)  );
        if (bHasTool)
            SG_ERR_CHECK(  SG_wc__diff__run(pCtx, pPathWc, pvhItem, &pvhResultCodes)  );
    }
    else
    {
        SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pStringGidRepoPath)  );
        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pStringGidRepoPath, "@%s", pszGid)  );

        SG_ERR_CHECK(  SG_STRINGARRAY__ALLOC(pCtx, &psa1, 1)  );
        SG_ERR_CHECK(  SG_stringarray__add(pCtx, psa1, SG_string__sz(pStringGidRepoPath))  );
        // we do not use the __throw() version of this routine so we can control
        // result-code processing below.
        SG_ERR_CHECK(  SG_vv2__diff_to_stream(pCtx, pOptSt->psz_repo, pOptSt->pRevSpec,
                                              psa1, 0,
                                              SG_FALSE,		// bNoSort
                                              SG_TRUE,		// bInteractive,
                                              pOptSt->psz_tool,
                                              &pvhResultCodes)  );
    }

    if (pvhResultCodes)
    {
        SG_vhash * pvhResult;				// we do not own this
        SG_ERR_CHECK(  SG_vhash__check__vhash(pCtx, pvhResultCodes, pszGid, &pvhResult)  );
        if (pvhResult)
        {
            const char * pszTool;

            SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, pvhResult, "tool", &pszTool)  );
            SG_ERR_CHECK(  SG_vhash__get__int64(pCtx, pvhResult, "result", &i64Result)  );

            SG_difftool__check_result_code__throw(pCtx, i64Result, pszTool);
            if (SG_context__has_err(pCtx))
            {
                SG_context__err_to_string(pCtx, SG_FALSE, &pStringErr);
                SG_context__err_reset(pCtx);
                SG_ERR_CHECK(  SG_console__raw(pCtx, SG_CS_STDERR, SG_string__sz(pStringErr))  );

                // eat the tool error. the result code is set.
            }
        }
    }

    if (piResult)
        *piResult = (SG_uint32)i64Result;

fail:
    SG_STRING_NULLFREE(pCtx, pStringGidRepoPath);
    SG_VHASH_NULLFREE(pCtx, pvhResultCodes);
    SG_STRINGARRAY_NULLFREE(pCtx, psa1);
    SG_STRING_NULLFREE(pCtx, pStringErr);
}
Пример #21
0
static void _fillInUserSelection(
	SG_context *pCtx,
	SG_string *pstrRepoDescriptorName,
	SG_string *replacement)
{
	SG_repo *repo = NULL;
	SG_varray *users = NULL;
	SG_vhash *user = NULL;
	SG_uint32 i = 0;
	SG_uint32 count;
	SG_string *semail = NULL;
	SG_string *suid = NULL;
	SG_string *entry = NULL;
	SG_string *curuid = NULL;

	SG_ERR_CHECK(  SG_string__clear(pCtx, replacement)  );
	SG_ERR_CHECK(  SG_repo__open_repo_instance(pCtx, SG_string__sz(pstrRepoDescriptorName), &repo)  );

	SG_ERR_CHECK(  SG_user__list_all(pCtx, repo, &users)  );
	SG_ERR_CHECK(  SG_varray__count(pCtx, users, &count)  );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &semail)  );
	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &suid)  );
	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &entry)  );

	SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &curuid)  );
	SG_ERR_CHECK(  _getUserId(pCtx, repo, curuid)  );

	for ( i = 0; i < count; ++i )
	{
		const char *uid = NULL;
		const char *email = NULL;
		const char *selected = NULL;

		SG_ERR_CHECK(  SG_varray__get__vhash(pCtx, users, i, &user)  );

		SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, user, "recid", &uid)  );
		SG_ERR_CHECK(  SG_vhash__get__sz(pCtx, user, "email", &email)  );

		SG_ERR_CHECK(  _getEncoded(pCtx, uid, suid)  );
		SG_ERR_CHECK(  _getEncoded(pCtx, email, semail)  );

		if (eq(SG_string__sz(curuid), uid))
		{
			selected = " selected='selected' ";
		}
		else
		{
			selected = "";
		}

		SG_ERR_CHECK(  SG_string__sprintf(pCtx, entry, "<option value=\"%s\" %s>%s</option>",
											SG_string__sz(suid), selected, SG_string__sz(semail))  );

		SG_ERR_CHECK(  SG_string__append__string(pCtx, replacement, entry)  );
	}
fail:
	SG_VARRAY_NULLFREE(pCtx, users);
	SG_REPO_NULLFREE(pCtx, repo);
	SG_STRING_NULLFREE(pCtx, semail);
	SG_STRING_NULLFREE(pCtx, suid);
	SG_STRING_NULLFREE(pCtx, entry);
	SG_STRING_NULLFREE(pCtx, curuid);
}
Пример #22
0
void SG_localsettings__get__variant(SG_context * pCtx, const char * psz_path, SG_repo* pRepo, SG_variant** ppv, SG_string** ppstr_where_found)
{
    SG_jsondb* p = NULL;
    SG_string* pstr_path = NULL;
    SG_variant* pv = NULL;
    char* psz_repo_id = NULL;
    char* psz_admin_id = NULL;
    const char* psz_ref_descriptor_name = NULL;

    SG_ASSERT(pCtx);
    SG_NONEMPTYCHECK_RETURN(psz_path);

    SG_ERR_CHECK(  SG_closet__get_localsettings(pCtx, &p)  );

    SG_ERR_CHECK(  SG_STRING__ALLOC(pCtx, &pstr_path)  );
    if ('/' == psz_path[0])
    {
        SG_bool b = SG_FALSE;

        SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s", psz_path)  );
        SG_ERR_CHECK(  SG_jsondb__has(pCtx, p, SG_string__sz(pstr_path), &b)  );
        if (b)
        {
            SG_ERR_CHECK(  SG_jsondb__get__variant(pCtx, p, SG_string__sz(pstr_path), &pv)  );
        }
    }
    else
    {
        SG_bool b_has_val = SG_FALSE;

        // try the instance of the repo
        if (!b_has_val && pRepo)
        {
            SG_ERR_CHECK(  SG_repo__get_descriptor_name(pCtx, pRepo, &psz_ref_descriptor_name)  );

            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s/%s",
                        SG_LOCALSETTING__SCOPE__INSTANCE,
                        psz_ref_descriptor_name,
                        psz_path
                        )  );
            SG_ERR_CHECK(  SG_jsondb__has(pCtx, p, SG_string__sz(pstr_path), &b_has_val)  );
            if (b_has_val)
            {
                SG_ERR_CHECK(  SG_jsondb__get__variant(pCtx, p, SG_string__sz(pstr_path), &pv)  );
            }
        }

        // then the repo
        if (!b_has_val && pRepo)
        {
            SG_ERR_CHECK(  SG_repo__get_repo_id(pCtx, pRepo, &psz_repo_id)  );

            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s/%s",
                        SG_LOCALSETTING__SCOPE__REPO,
                        psz_repo_id,
                        psz_path
                        )  );
            SG_ERR_CHECK(  SG_jsondb__has(pCtx, p, SG_string__sz(pstr_path), &b_has_val)  );
            if (b_has_val)
            {
                SG_ERR_CHECK(  SG_jsondb__get__variant(pCtx, p, SG_string__sz(pstr_path), &pv)  );
            }
        }

        // then the admin group of repos
        if (!b_has_val && pRepo)
        {
            SG_ERR_CHECK(  SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id)  );

            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s/%s",
                        SG_LOCALSETTING__SCOPE__ADMIN,
                        psz_admin_id,
                        psz_path
                        )  );
            SG_ERR_CHECK(  SG_jsondb__has(pCtx, p, SG_string__sz(pstr_path), &b_has_val)  );
            if (b_has_val)
            {
                SG_ERR_CHECK(  SG_jsondb__get__variant(pCtx, p, SG_string__sz(pstr_path), &pv)  );
            }
        }

        // then the machine
        if (!b_has_val)
        {
            SG_ERR_CHECK(  SG_string__sprintf(pCtx, pstr_path, "%s/%s", SG_LOCALSETTING__SCOPE__MACHINE, psz_path)  );
            SG_ERR_CHECK(  SG_jsondb__has(pCtx, p, SG_string__sz(pstr_path), &b_has_val)  );
            if (b_has_val)
            {
                SG_ERR_CHECK(  SG_jsondb__get__variant(pCtx, p, SG_string__sz(pstr_path), &pv)  );
            }
        }

        // then the factory default
        if (!b_has_val)
        {
            SG_STRING_NULLFREE(pCtx, pstr_path);
            SG_ERR_CHECK(  SG_localsettings__factory__get__variant(pCtx, psz_path, &pv)  );
        }
    }

    *ppv = pv;
    pv = NULL;

    if (ppstr_where_found)
    {
        *ppstr_where_found = pstr_path;
        pstr_path = NULL;
    }

fail:
    SG_NULLFREE(pCtx, psz_repo_id);
    SG_NULLFREE(pCtx, psz_admin_id);
    SG_VARIANT_NULLFREE(pCtx, pv);
    SG_STRING_NULLFREE(pCtx, pstr_path);
    SG_JSONDB_NULLFREE(pCtx, p);
}