📄 lock.c
字号:
{ const svn_wc_entry_t *t_entry, *p_entry, *t_entry_in_p; err = svn_wc_entry(&t_entry_in_p, path, p_access, FALSE, pool); if (! err) err = svn_wc_entry(&t_entry, path, t_access, FALSE, pool); if (! err) err = svn_wc_entry(&p_entry, parent, p_access, FALSE, pool); if (err) { svn_error_clear(p_access_err); svn_error_clear(do_close(p_access, FALSE, TRUE)); svn_error_clear(do_close(t_access, FALSE, TRUE)); return err; } /* Disjoint won't have PATH in P_ACCESS, switched will have incompatible URLs */ if (! t_entry_in_p || (p_entry->url && t_entry->url && (strcmp(svn_path_dirname(t_entry->url, pool), p_entry->url) || strcmp(svn_path_uri_encode(base_name, pool), svn_path_basename(t_entry->url, pool))))) { /* Switched or disjoint, so drop P_ACCESS */ err = do_close(p_access, FALSE, TRUE); if (err) { svn_error_clear(p_access_err); svn_error_clear(do_close(t_access, FALSE, TRUE)); return err; } p_access = NULL; } } if (p_access) { if (p_access_err) { /* Need P_ACCESS, so the read-only temporary won't do */ if (t_access) svn_error_clear(do_close(t_access, FALSE, TRUE)); svn_error_clear(do_close(p_access, FALSE, TRUE)); return p_access_err; } else if (t_access) join_batons(p_access, t_access, pool); } svn_error_clear(p_access_err); if (! t_access) { const svn_wc_entry_t *t_entry; err = svn_wc_entry(&t_entry, path, p_access, FALSE, pool); if (err) { if (p_access) svn_error_clear(do_close(p_access, FALSE, TRUE)); return err; } if (t_entry && t_entry->kind == svn_node_dir) { adm_ensure_set(p_access); apr_hash_set(p_access->set, apr_pstrdup(p_access->pool, path), APR_HASH_KEY_STRING, &missing); } } *anchor_access = p_access ? p_access : t_access; *target_access = t_access ? t_access : p_access; if (! p_access) *target = ""; else *target = base_name; } return SVN_NO_ERROR;}/* Does the work of closing the access baton ADM_ACCESS. Any physical locks are removed from the working copy if PRESERVE_LOCK is FALSE, or are left if PRESERVE_LOCK is TRUE. Any associated access batons that are direct descendents will also be closed. ### FIXME: If the set has a "hole", say it contains locks for the ### directories A, A/B, A/B/C/X but not A/B/C then closing A/B will not ### reach A/B/C/X . */static svn_error_t *do_close(svn_wc_adm_access_t *adm_access, svn_boolean_t preserve_lock, svn_boolean_t recurse){ if (adm_access->type == svn_wc__adm_access_closed) return SVN_NO_ERROR; /* Close descendant batons */ if (recurse && adm_access->set) { int i; apr_array_header_t *children = svn_sort__hash(adm_access->set, svn_sort_compare_items_as_paths, adm_access->pool); /* Go backwards through the list to close children before their parents. */ for (i = children->nelts - 1; i >= 0; --i) { svn_sort__item_t *item = &APR_ARRAY_IDX(children, i, svn_sort__item_t); const char *path = item->key; svn_wc_adm_access_t *child = item->value; if (child == &missing) { /* We don't close the missing entry, but get rid of it from the set. */ apr_hash_set(adm_access->set, path, APR_HASH_KEY_STRING, NULL); continue; } if (! svn_path_is_ancestor(adm_access->path, path) || strcmp(adm_access->path, path) == 0) continue; SVN_ERR(do_close(child, preserve_lock, FALSE)); } } /* Physically unlock if required */ if (adm_access->type == svn_wc__adm_access_write_lock) { if (adm_access->lock_exists && ! preserve_lock) { SVN_ERR(remove_lock(adm_access->path, adm_access->pool)); adm_access->lock_exists = FALSE; } } /* Reset to prevent further use of the lock. */ adm_access->type = svn_wc__adm_access_closed; /* Detach from set */ if (adm_access->set) { apr_hash_set(adm_access->set, adm_access->path, APR_HASH_KEY_STRING, NULL); assert(! adm_access->set_owner || apr_hash_count(adm_access->set) == 0); } return SVN_NO_ERROR;}svn_error_t *svn_wc_adm_close(svn_wc_adm_access_t *adm_access){ return do_close(adm_access, FALSE, TRUE);}svn_boolean_tsvn_wc_adm_locked(svn_wc_adm_access_t *adm_access){ return adm_access->type == svn_wc__adm_access_write_lock;}svn_error_t *svn_wc__adm_write_check(svn_wc_adm_access_t *adm_access){ if (adm_access->type == svn_wc__adm_access_write_lock) { if (adm_access->lock_exists) { /* Check physical lock still exists and hasn't been stolen. This really is paranoia, I have only ever seen one report of this triggering (from someone using the 0.25 release) and that was never reproduced. The check accesses the physical filesystem so it is expensive, but it only runs when we are going to modify the admin area. If it ever proves to be a bottleneck the physical check could be removed, just leaving the logical check. */ svn_boolean_t locked; SVN_ERR(svn_wc_locked(&locked, adm_access->path, adm_access->pool)); if (! locked) return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("Write-lock stolen in '%s'"), svn_path_local_style(adm_access->path, adm_access->pool)); } } else { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("No write-lock in '%s'"), svn_path_local_style(adm_access->path, adm_access->pool)); } return SVN_NO_ERROR;}svn_error_t *svn_wc_locked(svn_boolean_t *locked, const char *path, apr_pool_t *pool){ svn_node_kind_t kind; const char *lockfile = svn_wc__adm_path(path, 0, pool, SVN_WC__ADM_LOCK, NULL); SVN_ERR(svn_io_check_path(lockfile, &kind, pool)); if (kind == svn_node_file) *locked = TRUE; else if (kind == svn_node_none) *locked = FALSE; else return svn_error_createf(SVN_ERR_WC_LOCKED, NULL, _("Lock file '%s' is not a regular file"), svn_path_local_style(lockfile, pool)); return SVN_NO_ERROR;}const char *svn_wc_adm_access_path(svn_wc_adm_access_t *adm_access){ return adm_access->path;}apr_pool_t *svn_wc_adm_access_pool(svn_wc_adm_access_t *adm_access){ return adm_access->pool;}svn_error_t *svn_wc__adm_is_cleanup_required(svn_boolean_t *cleanup, svn_wc_adm_access_t *adm_access, apr_pool_t *pool){ if (adm_access->type == svn_wc__adm_access_write_lock) { svn_node_kind_t kind; const char *log_path = svn_wc__adm_path(svn_wc_adm_access_path(adm_access), FALSE, pool, SVN_WC__ADM_LOG, NULL); /* The presence of a log file demands cleanup */ SVN_ERR(svn_io_check_path(log_path, &kind, pool)); *cleanup = (kind == svn_node_file); } else *cleanup = FALSE; return SVN_NO_ERROR;}/* Ensure that the cache for the pruned hash (no deleted entries) in ADM_ACCESS is valid if the full hash is cached. POOL is used for local, short term, memory allocation. ### Should this sort of processing be in entries.c? */static voidprune_deleted(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){ if (! adm_access->entries && adm_access->entries_hidden) { apr_hash_index_t *hi; /* I think it will be common for there to be no deleted entries, so it is worth checking for that case as we can optimise it. */ for (hi = apr_hash_first(pool, adm_access->entries_hidden); hi; hi = apr_hash_next(hi)) { void *val; const svn_wc_entry_t *entry; apr_hash_this(hi, NULL, NULL, &val); entry = val; if ((entry->deleted && (entry->schedule != svn_wc_schedule_add) && (entry->schedule != svn_wc_schedule_replace)) || entry->absent) break; } if (! hi) { /* There are no deleted entries, so we can use the full hash */ adm_access->entries = adm_access->entries_hidden; return; } /* Construct pruned hash without deleted entries */ adm_access->entries = apr_hash_make(adm_access->pool); for (hi = apr_hash_first(pool, adm_access->entries_hidden); hi; hi = apr_hash_next(hi)) { void *val; const void *key; const svn_wc_entry_t *entry; apr_hash_this(hi, &key, NULL, &val); entry = val; if (((entry->deleted == FALSE) && (entry->absent == FALSE)) || (entry->schedule == svn_wc_schedule_add) || (entry->schedule == svn_wc_schedule_replace)) { apr_hash_set(adm_access->entries, key, APR_HASH_KEY_STRING, entry); } } }}voidsvn_wc__adm_access_set_entries(svn_wc_adm_access_t *adm_access, svn_boolean_t show_hidden, apr_hash_t *entries){ if (show_hidden) adm_access->entries_hidden = entries; else adm_access->entries = entries;}apr_hash_t *svn_wc__adm_access_entries(svn_wc_adm_access_t *adm_access, svn_boolean_t show_hidden, apr_pool_t *pool){ if (! show_hidden) { prune_deleted(adm_access, pool); return adm_access->entries; } else return adm_access->entries_hidden;}voidsvn_wc__adm_access_set_wcprops(svn_wc_adm_access_t *adm_access, apr_hash_t *wcprops){ adm_access->wcprops = wcprops;}apr_hash_t *svn_wc__adm_access_wcprops(svn_wc_adm_access_t *adm_access){ return adm_access->wcprops;}intsvn_wc__adm_wc_format(svn_wc_adm_access_t *adm_access){ return adm_access->wc_format;}voidsvn_wc__adm_set_wc_format(svn_wc_adm_access_t *adm_access, int format){ adm_access->wc_format = format;}svn_boolean_tsvn_wc__adm_missing(svn_wc_adm_access_t *adm_access, const char *path){ if (adm_access->set && apr_hash_get(adm_access->set, path, APR_HASH_KEY_STRING) == &missing) return TRUE; return FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -