📄 adm_crawler.c
字号:
iterpool)); } /* end file case */ /*** Directories (in recursive mode) ***/ else if (current_entry->kind == svn_node_dir && recurse) { svn_wc_adm_access_t *subdir_access; const svn_wc_entry_t *subdir_entry; /* If a directory is missing from disk, we have no way to recreate it locally, so report as missing and move along. Again, don't bother if we're reporting everything, because the dir is already missing on the server. */ if (missing) { if (! report_everything) SVN_ERR(reporter->delete_path(report_baton, this_path, iterpool)); continue; } /* We need to read the full entry of the directory from its own "this dir", if available. */ SVN_ERR(svn_wc_adm_retrieve(&subdir_access, adm_access, this_full_path, iterpool)); SVN_ERR(svn_wc_entry(&subdir_entry, this_full_path, subdir_access, TRUE, iterpool)); if (report_everything) { /* Report the dir unconditionally, one way or another. */ if (strcmp(subdir_entry->url, this_url) != 0) SVN_ERR(reporter->link_path(report_baton, this_path, subdir_entry->url, subdir_entry->revision, subdir_entry->incomplete, subdir_entry->lock_token, iterpool)); else SVN_ERR(reporter->set_path(report_baton, this_path, subdir_entry->revision, subdir_entry->incomplete, subdir_entry->lock_token, iterpool)); } /* Possibly report a disjoint URL ... */ else if (strcmp(subdir_entry->url, this_url) != 0) SVN_ERR(reporter->link_path(report_baton, this_path, subdir_entry->url, subdir_entry->revision, subdir_entry->incomplete, subdir_entry->lock_token, iterpool)); /* ... or perhaps just a differing revision, lock token or incomplete subdir. */ else if (subdir_entry->revision != dir_rev || subdir_entry->lock_token || subdir_entry->incomplete) SVN_ERR(reporter->set_path(report_baton, this_path, subdir_entry->revision, subdir_entry->incomplete, subdir_entry->lock_token, iterpool)); /* Recurse. */ SVN_ERR(report_revisions(adm_access, this_path, subdir_entry->revision, reporter, report_baton, notify_func, notify_baton, restore_files, recurse, subdir_entry->incomplete, use_commit_times, traversal_info, iterpool)); } /* end directory case */ } /* end main entries loop */ /* We're done examining this dir's entries, so free everything. */ svn_pool_destroy(subpool); return SVN_NO_ERROR;}/*------------------------------------------------------------------*//*** Public Interfaces ***//* This is the main driver of the working copy state "reporter", used for updates. */svn_error_t *svn_wc_crawl_revisions2(const char *path, svn_wc_adm_access_t *adm_access, const svn_ra_reporter2_t *reporter, void *report_baton, svn_boolean_t restore_files, svn_boolean_t recurse, svn_boolean_t use_commit_times, svn_wc_notify_func2_t notify_func, void *notify_baton, svn_wc_traversal_info_t *traversal_info, apr_pool_t *pool){ svn_error_t *fserr, *err = SVN_NO_ERROR; const svn_wc_entry_t *entry; svn_revnum_t base_rev = SVN_INVALID_REVNUM; svn_boolean_t missing = FALSE; const svn_wc_entry_t *parent_entry = NULL; svn_wc_notify_t *notify; /* The first thing we do is get the base_rev from the working copy's ROOT_DIRECTORY. This is the first revnum that entries will be compared to. */ SVN_ERR(svn_wc_entry(&entry, path, adm_access, FALSE, pool)); if ((! entry) || ((entry->schedule == svn_wc_schedule_add) && (entry->kind == svn_node_dir))) { SVN_ERR(svn_wc_entry(&parent_entry, svn_path_dirname(path, pool), adm_access, FALSE, pool)); base_rev = parent_entry->revision; SVN_ERR(reporter->set_path(report_baton, "", base_rev, entry ? entry->incomplete : TRUE, NULL, pool)); SVN_ERR(reporter->delete_path(report_baton, "", pool)); /* Finish the report, which causes the update editor to be driven. */ SVN_ERR(reporter->finish_report(report_baton, pool)); return SVN_NO_ERROR; } base_rev = entry->revision; if (base_rev == SVN_INVALID_REVNUM) { const char *dirname = svn_path_dirname(path, pool); SVN_ERR(svn_wc_entry(&parent_entry, dirname, adm_access, FALSE, pool)); if (! parent_entry) return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL, _("'%s' is not under version control"), svn_path_local_style(dirname, pool)); base_rev = parent_entry->revision; } /* The first call to the reporter merely informs it that the top-level directory being updated is at BASE_REV. Its PATH argument is ignored. */ SVN_ERR(reporter->set_path(report_baton, "", base_rev, entry->incomplete , /* start_empty ? */ NULL, pool)); if (entry->schedule != svn_wc_schedule_delete) { apr_finfo_t info; err = svn_io_stat(&info, path, APR_FINFO_MIN, pool); if (err) { if (APR_STATUS_IS_ENOENT(err->apr_err)) missing = TRUE; svn_error_clear(err); err = NULL; } } if (entry->kind == svn_node_dir) { if (missing) { /* Always report directories as missing; we can't recreate them locally. */ err = reporter->delete_path(report_baton, "", pool); if (err) goto abort_report; } else { /* Recursively crawl ROOT_DIRECTORY and report differing revisions. */ err = report_revisions(adm_access, "", base_rev, reporter, report_baton, notify_func, notify_baton, restore_files, recurse, entry->incomplete, use_commit_times, traversal_info, pool); if (err) goto abort_report; } } else if (entry->kind == svn_node_file) { const char *pdir, *bname; if (missing && restore_files) { /* Recreate file from text-base. */ err = restore_file(path, adm_access, use_commit_times, pool); if (err) goto abort_report; /* Report the restoration to the caller. */ if (notify_func != NULL) { notify = svn_wc_create_notify(path, svn_wc_notify_restore, pool); notify->kind = svn_node_file; (*notify_func)(notify_baton, notify, pool); } } /* Split PATH into parent PDIR and basename BNAME. */ svn_path_split(path, &pdir, &bname, pool); if (! parent_entry) { err = svn_wc_entry(&parent_entry, pdir, adm_access, FALSE, pool); if (err) goto abort_report; } if (parent_entry && parent_entry->url && entry->url && strcmp(entry->url, svn_path_url_add_component(parent_entry->url, bname, pool))) { /* This file is disjoint with respect to its parent directory. Since we are looking at the actual target of the report (not some file in a subdirectory of a target directory), and that target is a file, we need to pass an empty string to link_path. */ err = reporter->link_path(report_baton, "", entry->url, entry->revision, FALSE, entry->lock_token, pool); if (err) goto abort_report; } else if (entry->revision != base_rev || entry->lock_token) { /* If this entry is a file node, we just want to report that node's revision. Since we are looking at the actual target of the report (not some file in a subdirectory of a target directory), and that target is a file, we need to pass an empty string to set_path. */ err = reporter->set_path(report_baton, "", base_rev, FALSE, entry->lock_token, pool); if (err) goto abort_report; } } /* Finish the report, which causes the update editor to be driven. */ return reporter->finish_report(report_baton, pool); abort_report: /* Clean up the fs transaction. */ if ((fserr = reporter->abort_report(report_baton, pool))) { fserr = svn_error_quick_wrap(fserr, _("Error aborting report")); svn_error_compose(err, fserr); } return err;}/*** Compatibility wrapper: turns an svn_ra_reporter_t into an svn_ra_reporter2_t. ***/struct wrap_report_baton { const svn_ra_reporter_t *reporter; void *baton;};static svn_error_t *wrap_set_path(void *report_baton, const char *path, svn_revnum_t revision, svn_boolean_t start_empty, const char *lock_token, apr_pool_t *pool){ struct wrap_report_baton *wrb = report_baton; return wrb->reporter->set_path(wrb->baton, path, revision, start_empty, pool);}static svn_error_t *wrap_delete_path(void *report_baton, const char *path, apr_pool_t *pool){ struct wrap_report_baton *wrb = report_baton; return wrb->reporter->delete_path(wrb->baton, path, pool);} static svn_error_t *wrap_link_path(void *report_baton, const char *path, const char *url, svn_revnum_t revision, svn_boolean_t start_empty, const char *lock_token, apr_pool_t *pool){ struct wrap_report_baton *wrb = report_baton; return wrb->reporter->link_path(wrb->baton, path, url, revision, start_empty, pool);}static svn_error_t *wrap_finish_report(void *report_baton,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -