示例#1
0
static void _sg_workingdir__get_entry(SG_context* pCtx,
									  SG_repo* pRepo,
									  const SG_pathname* pPathSub,
									  const char * pszGid,
									  const SG_treenode_entry* pEntry,
									  SG_vhash * pvhTimestamps)
{
    SG_treenode_entry_type type;
    const char* pszidHidContent = NULL;
    const char* pszidHidXattrs = NULL;
    SG_int64 iAttributeBits = 0;

    SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pEntry, &type)  );
    SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pEntry, &pszidHidContent)  );
    SG_ERR_CHECK(  SG_treenode_entry__get_hid_xattrs(pCtx, pEntry, &pszidHidXattrs)  );
    SG_ERR_CHECK(  SG_treenode_entry__get_attribute_bits(pCtx, pEntry, &iAttributeBits)  );

	SG_ERR_CHECK(  _sg_workingdir__get_entry2(pCtx, pRepo, pPathSub,
											  pszGid,
											  type, pszidHidContent, pszidHidXattrs, iAttributeBits,
											  pvhTimestamps)  );

fail:
    return;
}
/**
 * INSERT or UPDATE this TreeNodeEntry and if a directory,
 * dive into it and INSERT/UPDATE the contents of the directory.
 */
void sg_wc_db__tne__insert_recursive(SG_context * pCtx,
									 sg_wc_db * pDb,
									 const sg_wc_db__cset_row * pCSetRow,
									 sqlite3_stmt * pStmt,
									 SG_uint64 uiAliasGidParent,
									 SG_uint64 uiAliasGid,
									 const SG_treenode_entry * pTreenodeEntry)
{
	SG_treenode * pTreenode = NULL;
	SG_uint32 nrEntries, k;
	SG_treenode_entry_type tneType;

	SG_ERR_CHECK(  sg_wc_db__tne__bind_insert_and_step(pCtx, pStmt,
													   uiAliasGid,
													   uiAliasGidParent,
													   pTreenodeEntry)  );
	
	SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pTreenodeEntry, &tneType)  );
	if (tneType == SG_TREENODEENTRY_TYPE_DIRECTORY)
	{
		const char * pszHid = NULL;				// we do not own this

		// dive into the contents of the directory and load them.

		SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pTreenodeEntry, &pszHid)  );
		SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx, pDb->pRepo, pszHid, &pTreenode)  );
	
		SG_ERR_CHECK(  SG_treenode__count(pCtx, pTreenode, &nrEntries)  );
		for (k=0; k<nrEntries; k++)
		{
			const char * pszGid_k = NULL;							// we do not own this
			const SG_treenode_entry * pTreenodeEntry_k = NULL;		// we do not own this
			SG_uint64 uiAliasGid_k = 0;

			SG_ERR_CHECK(  SG_treenode__get_nth_treenode_entry__ref(pCtx,
																	pTreenode,
																	k,
																	&pszGid_k,
																	&pTreenodeEntry_k)  );

			SG_ERR_CHECK(  sg_wc_db__gid__insert(pCtx, pDb, pszGid_k)  );
			SG_ERR_CHECK(  sg_wc_db__gid__get_alias_from_gid(pCtx, pDb, pszGid_k, &uiAliasGid_k)  );

			SG_ERR_CHECK(  sg_wc_db__tne__insert_recursive(pCtx, pDb, pCSetRow, pStmt,
														   uiAliasGid, uiAliasGid_k,
														   pTreenodeEntry_k)  );
		}
	}
	
fail:
	SG_TREENODE_NULLFREE(pCtx, pTreenode);
}
示例#3
0
void sg_pack__get_dir(SG_context* pCtx, SG_repo* pRepo, SG_int32 gen, const char* pszidHidTreeNode, SG_rbtree* prb_blobs, SG_rbtree* prb_new)
{
	SG_uint32 count;
	SG_uint32 i;
	SG_treenode* pTreenode = NULL;
    const char* psz_gid = NULL;
    SG_treenode_entry_type type;
    const char* psz_hid = NULL;

	SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx, pRepo, pszidHidTreeNode, &pTreenode)  );
	SG_ERR_CHECK(  SG_treenode__count(pCtx, pTreenode, &count)  );

	for (i=0; i<count; i++)
	{
		const SG_treenode_entry* pEntry = NULL;
		const char* pszName = NULL;

		SG_ERR_CHECK(  SG_treenode__get_nth_treenode_entry__ref(pCtx, pTreenode, i, &psz_gid, &pEntry)  );
		SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pEntry, &pszName)  );

        SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pEntry, &type)  );
        SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pEntry, &psz_hid)  );

        if (SG_TREENODEENTRY_TYPE_DIRECTORY == type)
        {
            SG_ERR_CHECK(  sg_pack__do_blob(pCtx, psz_gid, psz_hid, gen, prb_blobs, prb_new)  );
            SG_ERR_CHECK(  sg_pack__get_dir(pCtx, pRepo, gen, psz_hid, prb_blobs, prb_new)  );
        }
        else if (SG_TREENODEENTRY_TYPE_REGULAR_FILE == type)
        {
            /* TODO use pszName file extension to decide whether to bother? */
            SG_ERR_CHECK(  sg_pack__do_blob(pCtx, psz_gid, psz_hid, gen, prb_blobs, prb_new)  );
        }
        else if (SG_TREENODEENTRY_TYPE_SYMLINK == type)
        {
            /* ignore symlinks */
        }
        else
        {
            SG_ERR_THROW(  SG_ERR_NOTIMPLEMENTED  );
        }
	}

	SG_TREENODE_NULLFREE(pCtx, pTreenode);
	pTreenode = NULL;

	return;

fail:
	SG_TREENODE_NULLFREE(pCtx, pTreenode);
}
示例#4
0
/**
 * This function is used to get a new tree.  It must be called with the HID of
 * the top-level user root directory.  Not the super-root.  The directory which
 * corresponds to @. */
static void sg_pack__do_get_dir__top(SG_context* pCtx, SG_repo* pRepo, SG_int32 gen, const char* pszidHidTreeNode, SG_rbtree* prb_blobs, SG_rbtree* prb_new)
{
	SG_treenode* pTreenode = NULL;
	SG_byte* pBytes = NULL;
    const SG_treenode_entry* pEntry = NULL;
    const char* pszidHidContent = NULL;

    /* Load the treenode.  It should have exactly one entry, a subdirectory,
     * named @ */
	SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx, pRepo, pszidHidTreeNode, &pTreenode)  );
    SG_ERR_CHECK(  SG_treenode__get_nth_treenode_entry__ref(pCtx, pTreenode, 0, NULL, &pEntry)  );
    SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pEntry, &pszidHidContent)  );

#ifdef DEBUG
    {
        SG_uint32 count;
        SG_treenode_entry_type type;
        const char* pszName = NULL;

        SG_ERR_CHECK(  SG_treenode__count(pCtx, pTreenode, &count)  );
        SG_ASSERT(1 == count);

		SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pEntry, &type)  );
		SG_ASSERT (SG_TREENODEENTRY_TYPE_DIRECTORY == type);

		SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pEntry, &pszName)  );
        SG_ASSERT(0 == strcmp(pszName, "@"));
    }
#endif

    /* create the directory and then dive into it */
    SG_ERR_CHECK(  sg_pack__get_dir(pCtx, pRepo, gen, pszidHidContent, prb_blobs, prb_new)  );

	SG_TREENODE_NULLFREE(pCtx, pTreenode);

	return;

fail:
	/* TODO free stuff */
	SG_NULLFREE(pCtx, pBytes);
}
/**
 * BIND the fields for an INSERT or UPDATE a single row for this TreeNodeEntry (not
 * recursive) to the tne_L0 table.  Caller must compute the
 * GID aliases for the foreign keys and have already added
 * rows to tbl_gid as necessary.
 */
void sg_wc_db__tne__bind_insert(SG_context * pCtx,
								sqlite3_stmt * pStmt,
								SG_uint64 uiAliasGid,
								SG_uint64 uiAliasGidParent,
								const SG_treenode_entry * pTreenodeEntry)
{
	const char * pszHid = NULL;				// we do not own this
	const char * pszEntryname = NULL;		// we do not own this
	SG_int64 attrbits;
	SG_treenode_entry_type tneType;

	// pull all of the fields from the TNE.

	SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pTreenodeEntry, &pszHid)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pTreenodeEntry, &pszEntryname)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pTreenodeEntry, &tneType)  );
	SG_ERR_CHECK(  SG_treenode_entry__get_attribute_bits(pCtx, pTreenodeEntry, &attrbits)  );

#if TRACE_WC_ATTRBITS
	SG_ERR_IGNORE(  SG_console(pCtx, SG_CS_STDERR,
				   "TNE: bind_insert (%d) %s\n",
				   ((SG_uint32)attrbits),
				   pszEntryname)  );
#endif

	SG_ERR_CHECK(  sg_sqlite__reset(pCtx, pStmt)  );
	SG_ERR_CHECK(  sg_sqlite__clear_bindings(pCtx, pStmt)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 1, uiAliasGid)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 2, uiAliasGidParent)  );
	SG_ERR_CHECK(  sg_sqlite__bind_text__transient(pCtx, pStmt, 3, pszHid)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int(            pCtx, pStmt, 4, tneType)  );
	SG_ERR_CHECK(  sg_sqlite__bind_int64(          pCtx, pStmt, 5, attrbits)  );
	SG_ERR_CHECK(  sg_sqlite__bind_text__transient(pCtx, pStmt, 6, pszEntryname)  );

fail:
	return;
}
/**
 * Load the SuperRoot TreeNode from the Repo and completely
 * populate the tbl_L[k] table.
 *
 * WE DO NOT DROP/RECREATE THE TABLE BEFORE STARTING.
 * The caller should have prep'd the table if they want that.
 *
 * We DO NOT put the super-root in the tne_L0 table; we
 * start the tne_L0 table with the actual root "@/" (aka "@b/").
 * (Info on the super-root can be found in the tbl_csets.)
 * 
 */
void sg_wc_db__tne__process_super_root(SG_context * pCtx,
									   sg_wc_db * pDb,
									   const sg_wc_db__cset_row * pCSetRow,
									   sqlite3_stmt * pStmt,
									   const char * pszHidSuperRoot)
{
	SG_treenode * pTreenodeSuperRoot = NULL;
	const char * pszGidRoot = NULL;							// we don't own this
	const SG_treenode_entry * pTreenodeEntryRoot = NULL;	// we don't own this
	SG_uint64 uiAliasGidNull = 0;
	SG_uint64 uiAliasGidRoot = 0;

	SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx,
											   pDb->pRepo,
											   pszHidSuperRoot,
											   &pTreenodeSuperRoot)  );

#if defined(DEBUG)
	{
		// verify we have a well-formed super-root.  that is, the super-root treenode
		// should have exactly 1 treenode-entry -- the "@" (aka "@b/") directory.

		SG_uint32 nrEntries;
		
		SG_ERR_CHECK(  SG_treenode__count(pCtx, pTreenodeSuperRoot, &nrEntries)  );
		if (nrEntries != 1)
			SG_ERR_THROW(  SG_ERR_MALFORMED_SUPERROOT_TREENODE  );
	}
#endif

	SG_ERR_CHECK(  SG_treenode__get_nth_treenode_entry__ref(pCtx,
															pTreenodeSuperRoot,0,
															&pszGidRoot,
															&pTreenodeEntryRoot)  );
#if defined(DEBUG)
	{
		const char * pszEntrynameRoot = NULL;					// we don't own this
		SG_treenode_entry_type tneTypeRoot;

		SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pTreenodeEntryRoot, &pszEntrynameRoot)  );
		SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pTreenodeEntryRoot, &tneTypeRoot)  );
		// we set the root's entryname to "@" (not "@b") for
		// historical reasons and because that is what is in
		// the treenode. (We don't want it to look like
		// a rename if/when the corresponding row is created
		// in the tbl_PC table (where it should have "@").)
		if ( (strcmp(pszEntrynameRoot,"@") != 0) || (tneTypeRoot != SG_TREENODEENTRY_TYPE_DIRECTORY) )
			SG_ERR_THROW(  SG_ERR_MALFORMED_SUPERROOT_TREENODE  );
	}
#endif

	// alias for null-root has already been added.
	SG_ERR_CHECK(  sg_wc_db__gid__insert(pCtx, pDb, pszGidRoot)  );
	SG_ERR_CHECK(  sg_wc_db__gid__get_alias_from_gid(pCtx, pDb, SG_WC_DB__GID__NULL_ROOT, &uiAliasGidNull)  );
	SG_ERR_CHECK(  sg_wc_db__gid__get_alias_from_gid(pCtx, pDb, pszGidRoot,               &uiAliasGidRoot)  );

	SG_ERR_CHECK(  sg_wc_db__tne__insert_recursive(pCtx, pDb, pCSetRow, pStmt,
												   uiAliasGidNull, uiAliasGidRoot,
												   pTreenodeEntryRoot)  );

fail:
	SG_TREENODE_NULLFREE(pCtx, pTreenodeSuperRoot);
}
示例#7
0
/**
 * This function is used to get a new tree.  It must be called with the HID of
 * the top-level user root directory.  Not the super-root.  The directory which
 * corresponds to @.
 *
 * Record the file timestamp of each file we fetch in the pvhTimestamps; this
 * provides the basis for the timestamp check in scan-dir.
 */
static void sg_workingdir__do_get_dir__top(SG_context* pCtx,
										   SG_repo* pRepo,
										   const SG_pathname* pPathLocal,
										   const char* pszidHidTreeNode,
										   SG_vhash * pvhTimestamps)
{
	SG_pathname* pPathSub = NULL;
	SG_treenode* pTreenode = NULL;
	SG_string* pstrLink = NULL;
	SG_byte* pBytes = NULL;
    SG_vhash* pvhAttributes = NULL;
    SG_int64 iAttributeBits = 0;
    const SG_treenode_entry* pEntry = NULL;
    const char* pszidHidContent = NULL;
#ifdef SG_BUILD_FLAG_FEATURE_XATTR
    const char* pszidHidXattrs = NULL;
#endif
	SG_bool bExists = SG_FALSE;

    /* Load the treenode.  It should have exactly one entry, a subdirectory,
     * named @ */
	SG_ERR_CHECK(  SG_treenode__load_from_repo(pCtx, pRepo, pszidHidTreeNode, &pTreenode)  );
    SG_ERR_CHECK(  SG_treenode__get_nth_treenode_entry__ref(pCtx, pTreenode, 0, NULL, &pEntry)  );
    SG_ERR_CHECK(  SG_treenode_entry__get_hid_blob(pCtx, pEntry, &pszidHidContent)  );

#ifdef DEBUG
    {
        SG_uint32 count;
        SG_treenode_entry_type type;
        const char* pszName = NULL;

        SG_ERR_CHECK(  SG_treenode__count(pCtx, pTreenode, &count)  );
        SG_ASSERT(1 == count);

		SG_ERR_CHECK(  SG_treenode_entry__get_entry_type(pCtx, pEntry, &type)  );
		SG_ASSERT (SG_TREENODEENTRY_TYPE_DIRECTORY == type);

		SG_ERR_CHECK(  SG_treenode_entry__get_entry_name(pCtx, pEntry, &pszName)  );
        SG_ASSERT(0 == strcmp(pszName, "@"));
    }
#endif

    /* create the directory and then dive into it */
    SG_ERR_CHECK(  SG_PATHNAME__ALLOC__COPY(pCtx, &pPathSub, pPathLocal)  );
	SG_ERR_CHECK(  SG_fsobj__exists__pathname(pCtx, pPathSub, &bExists, NULL, NULL)  );
	if (!bExists)
		SG_ERR_CHECK(  SG_fsobj__mkdir__pathname(pCtx, pPathSub)  );
    SG_ERR_CHECK(  _sg_workingdir__get_dir(pCtx, pRepo, pPathSub, pszidHidContent, pvhTimestamps)  );

#ifdef SG_BUILD_FLAG_FEATURE_XATTR
    /* fix up the xattrs on that directory */
    SG_ERR_CHECK(  SG_treenode_entry__get_hid_xattrs(pCtx, pEntry, &pszidHidXattrs)  );
    if (pszidHidXattrs)
    {
        SG_ERR_CHECK(  SG_repo__fetch_vhash(pCtx, pRepo, pszidHidXattrs, &pvhAttributes)  );
        SG_ERR_CHECK(  SG_attributes__xattrs__apply(pCtx, pPathSub, pvhAttributes, pRepo)  );
        SG_VHASH_NULLFREE(pCtx, pvhAttributes);
    }
#endif

    /* and the attrbits too */
    SG_ERR_CHECK(  SG_treenode_entry__get_attribute_bits(pCtx, pEntry, &iAttributeBits)  );
    SG_ERR_CHECK(  SG_attributes__bits__apply(pCtx, pPathSub, iAttributeBits)  );

    SG_PATHNAME_NULLFREE(pCtx, pPathSub);
	SG_TREENODE_NULLFREE(pCtx, pTreenode);

	return;
fail:
	/* TODO free stuff */
    SG_VHASH_NULLFREE(pCtx, pvhAttributes);
	SG_NULLFREE(pCtx, pBytes);
	SG_STRING_NULLFREE(pCtx, pstrLink);
}