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; }
/** * 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; }
/** * 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); }