📄 info.c
字号:
/* * info.c: return system-generated metadata about paths or URLs. * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== *//* ==================================================================== */#include "client.h"#include "svn_client.h"#include "svn_wc.h"#include "svn_pools.h"#include "svn_path.h"#include "svn_private_config.h"/* Helper: build an svn_info_t *INFO struct from svn_dirent_t DIRENT and (possibly NULL) svn_lock_t LOCK, all allocated in POOL. Pointer fields are copied by reference, not dup'd. */static svn_error_t *build_info_from_dirent(svn_info_t **info, const svn_dirent_t *dirent, svn_lock_t *lock, const char *URL, svn_revnum_t revision, const char *repos_UUID, const char *repos_root, apr_pool_t *pool){ svn_info_t *tmpinfo = apr_pcalloc(pool, sizeof(*tmpinfo)); tmpinfo->URL = URL; tmpinfo->rev = revision; tmpinfo->kind = dirent->kind; tmpinfo->repos_UUID = repos_UUID; tmpinfo->repos_root_URL = repos_root; tmpinfo->last_changed_rev = dirent->created_rev; tmpinfo->last_changed_date = dirent->time; tmpinfo->last_changed_author = dirent->last_author;; tmpinfo->lock = lock; *info = tmpinfo; return SVN_NO_ERROR;}/* Helper: build an svn_info_t *INFO struct from svn_wc_entry_t ENTRY, allocated in POOL. Pointer fields are copied by reference, not dup'd. */static svn_error_t *build_info_from_entry(svn_info_t **info, const svn_wc_entry_t *entry, apr_pool_t *pool){ svn_info_t *tmpinfo = apr_pcalloc(pool, sizeof(*tmpinfo)); tmpinfo->URL = entry->url; tmpinfo->rev = entry->revision; tmpinfo->kind = entry->kind; tmpinfo->repos_UUID = entry->uuid; tmpinfo->repos_root_URL = entry->repos; tmpinfo->last_changed_rev = entry->cmt_rev; tmpinfo->last_changed_date = entry->cmt_date; tmpinfo->last_changed_author = entry->cmt_author; /* entry-specific stuff */ tmpinfo->has_wc_info = TRUE; tmpinfo->schedule = entry->schedule; tmpinfo->copyfrom_url = entry->copyfrom_url; tmpinfo->copyfrom_rev = entry->copyfrom_rev; tmpinfo->text_time = entry->text_time; tmpinfo->prop_time = entry->prop_time; tmpinfo->checksum = entry->checksum; tmpinfo->conflict_old = entry->conflict_old; tmpinfo->conflict_new = entry->conflict_new; tmpinfo->conflict_wrk = entry->conflict_wrk; tmpinfo->prejfile = entry->prejfile; /* lock stuff */ if (entry->lock_token) /* the token is the critical bit. */ { tmpinfo->lock = apr_pcalloc(pool, sizeof(*(tmpinfo->lock))); tmpinfo->lock->token = entry->lock_token; tmpinfo->lock->owner = entry->lock_owner; tmpinfo->lock->comment = entry->lock_comment; tmpinfo->lock->creation_date = entry->lock_creation_date; } *info = tmpinfo; return SVN_NO_ERROR;}/* The dirent fields we care about for our calls to svn_ra_get_dir2. */#define DIRENT_FIELDS (SVN_DIRENT_KIND | \ SVN_DIRENT_CREATED_REV | \ SVN_DIRENT_TIME | \ SVN_DIRENT_LAST_AUTHOR)/* Helper func for recursively fetching svn_dirent_t's from a remote directory and pushing them at an info-receiver callback. */static svn_error_t *push_dir_info(svn_ra_session_t *ra_session, const char *session_URL, const char *dir, svn_revnum_t rev, const char *repos_UUID, const char *repos_root, svn_info_receiver_t receiver, void *receiver_baton, svn_client_ctx_t *ctx, apr_hash_t *locks, apr_pool_t *pool){ apr_hash_t *tmpdirents; svn_dirent_t *the_ent; svn_info_t *info; apr_hash_index_t *hi; apr_pool_t *subpool = svn_pool_create(pool); SVN_ERR(svn_ra_get_dir2(ra_session, &tmpdirents, NULL, NULL, dir, rev, DIRENT_FIELDS, pool)); for (hi = apr_hash_first(pool, tmpdirents); hi; hi = apr_hash_next(hi)) { const char *path, *URL, *fs_path; const void *key; svn_lock_t *lock; void *val; svn_pool_clear(subpool); if (ctx->cancel_func) SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); apr_hash_this(hi, &key, NULL, &val); the_ent = val; path = svn_path_join(dir, key, subpool); URL = svn_path_url_add_component(session_URL, key, subpool); fs_path = svn_path_is_child(repos_root, URL, subpool); fs_path = apr_pstrcat(subpool, "/", fs_path, NULL); fs_path = svn_path_uri_decode(fs_path, subpool); lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING); SVN_ERR(build_info_from_dirent(&info, the_ent, lock, URL, rev, repos_UUID, repos_root, subpool)); SVN_ERR(receiver(receiver_baton, path, info, subpool)); if (the_ent->kind == svn_node_dir) SVN_ERR(push_dir_info(ra_session, URL, path, rev, repos_UUID, repos_root, receiver, receiver_baton, ctx, locks, subpool)); } svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Callback and baton for crawl_entries() walk over entries files. */struct found_entry_baton{ svn_info_receiver_t receiver; void *receiver_baton; };static svn_error_t *info_found_entry_callback(const char *path, const svn_wc_entry_t *entry, void *walk_baton, apr_pool_t *pool){ struct found_entry_baton *fe_baton = walk_baton; svn_info_t *info; /* We're going to receive dirents twice; we want to ignore the first one (where it's a child of a parent dir), and only print the second one (where we're looking at THIS_DIR.) */ if ((entry->kind == svn_node_dir) && (strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR))) return SVN_NO_ERROR; SVN_ERR(build_info_from_entry(&info, entry, pool)); return fe_baton->receiver(fe_baton->receiver_baton, path, info, pool);}static const svn_wc_entry_callbacks_t entry_walk_callbacks = { info_found_entry_callback };/* Helper function: push the svn_wc_entry_t for WCPATH at RECEIVER/BATON, and possibly recurse over more entries. */static svn_error_t *crawl_entries(const char *wcpath, svn_info_receiver_t receiver, void *receiver_baton, svn_boolean_t recurse, svn_client_ctx_t *ctx, apr_pool_t *pool){ svn_wc_adm_access_t *adm_access; const svn_wc_entry_t *entry; svn_info_t *info; struct found_entry_baton fe_baton; SVN_ERR(svn_wc_adm_probe_open3(&adm_access, NULL, wcpath, FALSE, recurse ? -1 : 0, ctx->cancel_func, ctx->cancel_baton, pool)); SVN_ERR(svn_wc_entry(&entry, wcpath, adm_access, FALSE, pool)); if (! entry) { return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL, _("Cannot read entry for '%s'"), wcpath); } SVN_ERR(build_info_from_entry(&info, entry, pool)); fe_baton.receiver = receiver; fe_baton.receiver_baton = receiver_baton; if (entry->kind == svn_node_file) return receiver(receiver_baton, wcpath, info, pool); else if (entry->kind == svn_node_dir) { if (recurse) SVN_ERR(svn_wc_walk_entries2(wcpath, adm_access, &entry_walk_callbacks, &fe_baton, FALSE, ctx->cancel_func, ctx->cancel_baton, pool)); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -