static void _getDescriptorName( SG_context *pCtx, const _request_headers *pRequestHeaders, SG_string **ppRepoName) { SG_pathname *pPathCwd = NULL; if (_startsWith("repos/", pRequestHeaders->pUri) && (strlen(pRequestHeaders->pUri) > 6)) { const char *nameStart = pRequestHeaders->pUri + 6; const char *nameEnd = strchr(nameStart, '/'); SG_ERR_CHECK( SG_STRING__ALLOC(pCtx, ppRepoName) ); if (nameEnd == NULL) SG_ERR_CHECK( SG_string__set__sz(pCtx, *ppRepoName, nameStart) ); else SG_ERR_CHECK( SG_string__set__buf_len(pCtx, *ppRepoName, (const SG_byte *)nameStart, (nameEnd - nameStart) * sizeof(char)) ); } else { SG_ERR_CHECK( SG_PATHNAME__ALLOC(pCtx, &pPathCwd) ); SG_ERR_CHECK( SG_pathname__set__from_cwd(pCtx, pPathCwd) ); SG_ERR_CHECK( SG_workingdir__find_mapping(pCtx, pPathCwd, NULL, ppRepoName, NULL) ); } fail: SG_PATHNAME_NULLFREE(pCtx, pPathCwd); }
/** * 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); }
static void _getUserId( SG_context *pCtx, SG_repo *repo, SG_string *userid) { SG_audit u; SG_ERR_CHECK( SG_audit__init__maybe_nobody(pCtx, &u, repo, SG_AUDIT__WHEN__NOW, SG_AUDIT__WHO__FROM_SETTINGS) ); SG_ERR_CHECK( SG_string__set__sz(pCtx, userid, u.who_szUserId) ); fail: ; }
static void _todo_replacer( SG_context * pCtx, const _request_headers *pRequestHeaders, SG_string *keyword, SG_string *replacement) { SG_UNUSED(pRequestHeaders); if (seq(keyword, "TITLE")) { SG_ERR_CHECK_RETURN( SG_string__set__sz(pCtx, replacement, "veracity / todo") ); } }
static void _getUserEmail(SG_context *pCtx, SG_repo* pRepo, SG_string *replacement) { SG_vhash* pvh_user = NULL; SG_string* pstrUser = NULL; const char* psz_email = NULL; SG_STRING__ALLOC(pCtx, &pstrUser); SG_ERR_CHECK( _getUserId(pCtx, pRepo, pstrUser) ); SG_ERR_CHECK( SG_user__lookup_by_userid(pCtx, pRepo, SG_string__sz(pstrUser), &pvh_user) ); if (pvh_user) { SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_user, "email", &psz_email) ); } SG_ERR_CHECK( SG_string__set__sz(pCtx, replacement, psz_email) ); fail: SG_VHASH_NULLFREE(pCtx, pvh_user); SG_STRING_NULLFREE(pCtx, pstrUser); }
void SG_cmd_util__get_username_and_password( SG_context *pCtx, const char *szWhoami, SG_bool force_whoami, SG_bool bHadSavedCredentials, SG_uint32 kAttempt, SG_string **ppUsername, SG_string **ppPassword ) { SG_string * pUsername = NULL; SG_string * pPassword = NULL; SG_NULLARGCHECK_RETURN(ppPassword); SG_NULLARGCHECK_RETURN(ppUsername); if (kAttempt == 0) { if (bHadSavedCredentials) { SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "\nAuthorization required. Saved username/password not valid.\n") ); } else { SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "\nAuthorization required.") ); if (SG_password__supported()) SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, " Use --remember to save this password.") ); SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "\n") ); } } else if (kAttempt >= 3) { SG_ERR_THROW( SG_ERR_AUTHORIZATION_TOO_MANY_ATTEMPTS ); } else { SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "\nInvalid username or password. Please try again.\n") ); } if(szWhoami!=NULL && force_whoami) { SG_ERR_CHECK( SG_STRING__ALLOC__SZ(pCtx, &pUsername, szWhoami) ); SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "Enter password for %s: ", szWhoami) ); SG_ERR_CHECK( SG_console__get_password(pCtx, &pPassword) ); } else { if(szWhoami) { SG_bool bAllWhitespace = SG_FALSE; SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "Enter username [%s]: ", szWhoami) ); SG_ERR_CHECK( SG_console__readline_stdin(pCtx, &pUsername) ); SG_ERR_CHECK( SG_sz__is_all_whitespace(pCtx, SG_string__sz(pUsername), &bAllWhitespace) ); if(bAllWhitespace) SG_ERR_CHECK( SG_string__set__sz(pCtx, pUsername, szWhoami) ); } else { SG_ERR_CHECK( SG_console(pCtx, SG_CS_STDERR, "Enter username: "******"Enter password: ") ); SG_ERR_CHECK( SG_console__get_password(pCtx, &pPassword) ); } *ppUsername = pUsername; *ppPassword = pPassword; return; fail: SG_STRING_NULLFREE(pCtx, pUsername); SG_STRING_NULLFREE(pCtx, pPassword); }
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); }
void SG_localsettings__split_full_name( SG_context* pCtx, const char* szFullName, SG_uint32* uSplitIndex, SG_string* pScopeName, SG_string* pSettingName ) { SG_uint32 uSlashCount = 0; SG_uint32 uCurrent = 0; SG_ARGCHECK(szFullName[0] == '/', szFullName); // this is basically implemented by locating the Nth '/' character // where N depends on which scope the name is in if (0 == strncmp(szFullName, SG_LOCALSETTING__SCOPE__INSTANCE, strlen(SG_LOCALSETTING__SCOPE__INSTANCE))) { uSlashCount = 2; } else if (0 == strncmp(szFullName, SG_LOCALSETTING__SCOPE__REPO, strlen(SG_LOCALSETTING__SCOPE__REPO))) { uSlashCount = 2; } else if (0 == strncmp(szFullName, SG_LOCALSETTING__SCOPE__ADMIN, strlen(SG_LOCALSETTING__SCOPE__ADMIN))) { uSlashCount = 2; } else if (0 == strncmp(szFullName, SG_LOCALSETTING__SCOPE__MACHINE, strlen(SG_LOCALSETTING__SCOPE__MACHINE))) { uSlashCount = 1; } else { uSlashCount = 1; } // iterate through the string until we find the slash that we're looking for while (szFullName[uCurrent] != '\0' && uSlashCount > 0u) { // the first time through, this will always skip the leading slash character // this is why uSlashCount is one less than it seems like it should be uCurrent = uCurrent + 1u; // if this is a slash, update our count if (szFullName[uCurrent] == '/') { uSlashCount = uSlashCount - 1; } } // if the caller wants the index, fill it in if (uSplitIndex != NULL) { *uSplitIndex = uCurrent; } // if the caller wants the scope name, fill it in if (pScopeName != NULL) { SG_ERR_CHECK( SG_string__set__buf_len(pCtx, pScopeName, (const SG_byte*)szFullName, uCurrent) ); } // if the caller wants the setting name, fill it in if (pSettingName != NULL) { SG_ERR_CHECK( SG_string__set__sz(pCtx, pSettingName, szFullName + uCurrent + 1) ); } fail: return; }