📄 adm_crawler.c
字号:
goto abort_report;
/* Report the restoration to the caller. */
if (notify_func != NULL)
(*notify_func) (notify_baton, path, svn_wc_notify_restore,
svn_node_file,
NULL,
svn_wc_notify_state_unknown,
svn_wc_notify_state_unknown,
SVN_INVALID_REVNUM);
}
/* Split PATH into parent PDIR and basename BNAME. */
svn_path_split (path, &pdir, &bname, pool);
if (! parent_entry)
SVN_ERR (svn_wc_entry (&parent_entry, pdir, adm_access, FALSE, pool));
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. */
SVN_ERR (reporter->link_path (report_baton,
"",
entry->url,
entry->revision,
FALSE,
pool));
}
else if (entry->revision != base_rev)
{
/* 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, pool);
if (err)
goto abort_report;
}
}
/* Finish the report, which causes the update editor to be driven. */
SVN_ERR (reporter->finish_report (report_baton, pool));
abort_report:
if (err)
{
/* Clean up the fs transaction. */
svn_error_t *fserr;
if ((fserr = reporter->abort_report (report_baton, pool)))
{
fserr = svn_error_quick_wrap (fserr, _("Error aborting report"));
svn_error_compose (err, fserr);
}
return err;
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_wc_transmit_text_deltas (const char *path,
svn_wc_adm_access_t *adm_access,
svn_boolean_t fulltext,
const svn_delta_editor_t *editor,
void *file_baton,
const char **tempfile,
apr_pool_t *pool)
{
const char *tmpf, *tmp_base;
svn_txdelta_window_handler_t handler;
void *wh_baton;
svn_txdelta_stream_t *txdelta_stream;
apr_file_t *localfile = NULL;
apr_file_t *basefile = NULL;
const char *base_digest_hex = NULL;
unsigned char digest[APR_MD5_DIGESTSIZE];
/* Make an untranslated copy of the working file in the
administrative tmp area because a) we want this to work even if
someone changes the working file while we're generating the
txdelta, b) we need to detranslate eol and keywords anyway, and
c) after the commit, we're going to copy the tmp file to become
the new text base anyway. */
SVN_ERR (svn_wc_translated_file (&tmpf, path, adm_access, FALSE, pool));
/* If the translation didn't create a new file then we need an explicit
copy, if it did create a new file we need to rename it. */
tmp_base = svn_wc__text_base_path (path, TRUE, pool);
if (tmpf == path)
SVN_ERR (svn_io_copy_file (tmpf, tmp_base, FALSE, pool));
else
SVN_ERR (svn_io_file_rename (tmpf, tmp_base, pool));
/* If we're not sending fulltext, we'll be sending diffs against the
text-base. */
if (! fulltext)
{
/* Before we set up an svndiff stream against the old text base,
make sure the old text base still matches its checksum.
Otherwise we could send corrupt data and never know it. */
const svn_wc_entry_t *ent;
SVN_ERR (svn_wc_entry (&ent, path, adm_access, FALSE, pool));
/* For backwards compatibility, no checksum means assume a match. */
if (ent->checksum)
{
const char *tb = svn_wc__text_base_path (path, FALSE, pool);
unsigned char tb_digest[APR_MD5_DIGESTSIZE];
SVN_ERR (svn_io_file_checksum (tb_digest, tb, pool));
base_digest_hex = svn_md5_digest_to_cstring (tb_digest, pool);
if (strcmp (base_digest_hex, ent->checksum) != 0)
{
/* Compatibility hack: working copies created before
13 Jan 2003 may have entry checksums stored in
base64. See svn_io_file_checksum_base64()'s doc
string for details. */
const char *digest_base64
= (svn_base64_from_md5 (tb_digest, pool))->data;
if (strcmp (digest_base64, ent->checksum) != 0)
{
/* There is an entry checksum, but it does not match
the actual text base checksum. Extreme badness.
Of course, theoretically we could just switch to
fulltext transmission here, and everything would
work fine; after all, we're going to replace the
text base with a new one in a moment anyway, and
we'd fix the checksum then. But it's better to
error out. People should know that their text
bases are getting corrupted, so they can
investigate. Other commands could be affected,
too, such as `svn diff'. */
/* Deliberately ignore error; the error about the
checksum mismatch is more important to return.
And wrapping the above error into the checksum
error would be weird, as they're unrelated. */
svn_error_clear (svn_io_remove_file (tmp_base, pool));
if (tempfile)
*tempfile = NULL;
return svn_error_createf
(SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL,
_("Checksum mismatch for '%s'; "
"expected '%s', actual: '%s'"),
tb, ent->checksum, base_digest_hex);
}
}
}
SVN_ERR (svn_wc__open_text_base (&basefile, path, APR_READ, pool));
}
/* Tell the editor that we're about to apply a textdelta to the
file baton; the editor returns to us a window consumer routine
and baton. */
SVN_ERR (editor->apply_textdelta
(file_baton,
base_digest_hex, pool, &handler, &wh_baton));
/* Alert the caller that we have created a temporary file that might
need to be cleaned up. */
if (tempfile)
*tempfile = tmp_base;
/* Open a filehandle for tmp text-base. */
SVN_ERR_W (svn_io_file_open (&localfile, tmp_base,
APR_READ, APR_OS_DEFAULT, pool),
_("Error opening local file"));
/* Create a text-delta stream object that pulls data out of the two
files. */
svn_txdelta (&txdelta_stream,
svn_stream_from_aprfile (basefile, pool),
svn_stream_from_aprfile (localfile, pool),
pool);
/* Pull windows from the delta stream and feed to the consumer. */
SVN_ERR (svn_txdelta_send_txstream (txdelta_stream, handler,
wh_baton, pool));
/* Close the two files */
SVN_ERR (svn_io_file_close (localfile, pool));
if (basefile)
SVN_ERR (svn_wc__close_text_base (basefile, path, 0, pool));
/* ### This is a pity. tmp_base was created with svn_io_copy_file()
above, which uses apr_file_copy(), which probably called
apr_file_transfer_contents(), which ran over every byte of the
file and therefore could have computed a checksum effortlessly.
But we're not about to change the interface of apr_file_copy(),
so we'll have to run over the bytes again... */
SVN_ERR (svn_io_file_checksum (digest, tmp_base, pool));
/* Close the file baton, and get outta here. */
return editor->close_file
(file_baton, svn_md5_digest_to_cstring (digest, pool), pool);
}
svn_error_t *
svn_wc_transmit_prop_deltas (const char *path,
svn_wc_adm_access_t *adm_access,
const svn_wc_entry_t *entry,
const svn_delta_editor_t *editor,
void *baton,
const char **tempfile,
apr_pool_t *pool)
{
int i;
const char *props, *props_base, *props_tmp;
apr_array_header_t *propmods;
apr_hash_t *localprops = apr_hash_make (pool);
apr_hash_t *baseprops = apr_hash_make (pool);
/* Get the right access baton for the job. */
SVN_ERR (svn_wc_adm_probe_retrieve (&adm_access, adm_access, path, pool));
/* First, get the prop_path from the original path */
SVN_ERR (svn_wc__prop_path (&props, path, adm_access, FALSE, pool));
/* Get the full path of the prop-base `pristine' file */
if (entry->schedule == svn_wc_schedule_replace)
{
/* do nothing: baseprop hash should be -empty- for comparison
purposes. if they already exist on disk, they're "leftover"
from the old file that was replaced. */
props_base = NULL;
}
else
/* the real prop-base hash */
SVN_ERR (svn_wc__prop_base_path (&props_base, path, adm_access, FALSE,
pool));
/* Copy the local prop file to the administrative temp area */
SVN_ERR (svn_wc__prop_path (&props_tmp, path, adm_access, TRUE, pool));
SVN_ERR (svn_io_copy_file (props, props_tmp, FALSE, pool));
/* Alert the caller that we have created a temporary file that might
need to be cleaned up. */
if (tempfile)
*tempfile = props_tmp;
/* Load all properties into hashes */
SVN_ERR (svn_wc__load_prop_file (props_tmp, localprops, pool));
if (props_base)
SVN_ERR (svn_wc__load_prop_file (props_base, baseprops, pool));
/* Get an array of local changes by comparing the hashes. */
SVN_ERR (svn_prop_diffs (&propmods, localprops, baseprops, pool));
/* Apply each local change to the baton */
for (i = 0; i < propmods->nelts; i++)
{
const svn_prop_t *p = &APR_ARRAY_IDX (propmods, i, svn_prop_t);
if (entry->kind == svn_node_file)
SVN_ERR (editor->change_file_prop (baton, p->name, p->value, pool));
else
SVN_ERR (editor->change_dir_prop (baton, p->name, p->value, pool));
}
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -