static void _get_baseline(SG_context * pCtx, SG_pendingtree * pPendingTree, char ** ppszBaseline) { const SG_varray * pvaParents; const char * pszBaseline; char * pszAllocated = NULL; // get the HID of the BASELINE (aka PARENT[0] from the pendingtree). SG_ERR_CHECK( SG_pendingtree__get_wd_parents__ref(pCtx, pPendingTree, &pvaParents) ); SG_ERR_CHECK( SG_varray__get__sz(pCtx, pvaParents, 0, &pszBaseline) ); SG_ERR_CHECK( SG_strdup(pCtx, pszBaseline, &pszAllocated) ); *ppszBaseline = pszAllocated; return; fail: SG_NULLFREE(pCtx, pszAllocated); }
void SG_tag__add_tags(SG_context * pCtx, SG_repo * pRepo, SG_pendingtree * pPendingTree, const char* psz_spec_cs, SG_bool bRev, SG_bool bForce, const char** ppszTags, SG_uint32 count_args) { SG_pathname* pPathCwd = NULL; char* psz_hid_cs = NULL; SG_audit q; SG_uint32 i = 0; char * psz_current_hid_with_that_tag = NULL; SG_bool bFreePendingTree = SG_FALSE; SG_ERR_CHECK( SG_audit__init(pCtx,&q,pRepo,SG_AUDIT__WHEN__NOW,SG_AUDIT__WHO__FROM_SETTINGS) ); // TODO 4/21/10 pendingtree contains a pRepo inside it. we should // TODO 4/21/10 refactor this to alloc the pendingtree first and then // TODO 4/21/10 just borrow the pRepo from it. if (psz_spec_cs) { if (bRev) { SG_ERR_CHECK( SG_repo__hidlookup__dagnode(pCtx, pRepo, SG_DAGNUM__VERSION_CONTROL, psz_spec_cs, &psz_hid_cs) ); } else { SG_ERR_CHECK( SG_vc_tags__lookup__tag(pCtx, pRepo, psz_spec_cs, &psz_hid_cs) ); if (psz_hid_cs == NULL) SG_ERR_THROW(SG_ERR_TAG_NOT_FOUND); } } else { // tag the current baseline. // // when we have an uncomitted merge, we will have more than one parent. // what does this command mean then? It feels like we we should throw // an error and say that you have to commit first. const SG_varray * pva_wd_parents; // we do not own this const char * psz_hid_parent_0; // we do not own this SG_uint32 nrParents; if (pPendingTree == NULL) { SG_ERR_CHECK( SG_pendingtree__alloc_from_cwd(pCtx, SG_TRUE, &pPendingTree) ); bFreePendingTree = SG_TRUE; } SG_ERR_CHECK( SG_pendingtree__get_wd_parents__ref(pCtx, pPendingTree, &pva_wd_parents) ); SG_ERR_CHECK( SG_varray__count(pCtx, pva_wd_parents, &nrParents) ); if (nrParents > 1) SG_ERR_THROW( SG_ERR_CANNOT_DO_WHILE_UNCOMMITTED_MERGE ); SG_ERR_CHECK( SG_varray__get__sz(pCtx, pva_wd_parents, 0, &psz_hid_parent_0) ); SG_ERR_CHECK( SG_strdup(pCtx, psz_hid_parent_0, &psz_hid_cs) ); } if (!bForce) { //Go through and check all tags to make sure that they are not already applied. for (i = 0; i < count_args; i++) { const char * pszTag = ppszTags[i]; SG_ERR_IGNORE( SG_vc_tags__lookup__tag(pCtx, pRepo, pszTag, &psz_current_hid_with_that_tag) ); if (psz_current_hid_with_that_tag != NULL && 0 != strcmp(psz_current_hid_with_that_tag, psz_hid_cs)) //The tag has been applied, but not to the given changeset. SG_ERR_THROW(SG_ERR_TAG_ALREADY_EXISTS); SG_NULLFREE(pCtx, psz_current_hid_with_that_tag); } } for (i = 0; i < count_args; i++) { const char * pszTag = ppszTags[i]; SG_ERR_CHECK( SG_vc_tags__lookup__tag(pCtx, pRepo, pszTag, &psz_current_hid_with_that_tag) ); if (psz_current_hid_with_that_tag == NULL || 0 != strcmp(psz_current_hid_with_that_tag, psz_hid_cs)) { //The tag has not been applied, or it's been applied to a different dagnode. if ( psz_current_hid_with_that_tag != NULL && bForce) //Remove it, if it's already there SG_ERR_CHECK( SG_vc_tags__remove(pCtx, pRepo, &q, 1, &pszTag) ); SG_ERR_CHECK( SG_vc_tags__add(pCtx, pRepo, psz_hid_cs, pszTag, &q) ); } SG_NULLFREE(pCtx, psz_current_hid_with_that_tag); } fail: SG_NULLFREE(pCtx, psz_current_hid_with_that_tag); if (bFreePendingTree == SG_TRUE) SG_PENDINGTREE_NULLFREE(pCtx, pPendingTree); SG_NULLFREE(pCtx, psz_hid_cs); SG_PATHNAME_NULLFREE(pCtx, pPathCwd); }