static svn_error_t * parse_spool_file(svn_ra_neon__session_t *ras, const char *spool_file_name, ne_xml_parser *success_parser, apr_pool_t *pool) { svn_stream_t *spool_stream; char *buf = apr_palloc(pool, SVN__STREAM_CHUNK_SIZE); apr_size_t len; SVN_ERR(svn_stream_open_readonly(&spool_stream, spool_file_name, pool, pool)); while (1) { if (ras->callbacks && ras->callbacks->cancel_func) SVN_ERR((ras->callbacks->cancel_func)(ras->callback_baton)); len = SVN__STREAM_CHUNK_SIZE; SVN_ERR(svn_stream_read(spool_stream, buf, &len)); if (len > 0) if (ne_xml_parse(success_parser, buf, len) != 0) /* The parse encountered an error or was aborted by a user defined callback */ break; if (len != SVN__STREAM_CHUNK_SIZE) break; } return svn_stream_close(spool_stream); }
svn_error_t * svn_subst_stream_detranslated(svn_stream_t **stream_p, const char *src, svn_subst_eol_style_t eol_style, const char *eol_str, svn_boolean_t always_repair_eols, apr_hash_t *keywords, svn_boolean_t special, apr_pool_t *pool) { svn_stream_t *src_stream; if (special) return svn_subst_read_specialfile(stream_p, src, pool, pool); /* This will be closed by svn_subst_stream_translated_to_normal_form when the returned stream is closed. */ SVN_ERR(svn_stream_open_readonly(&src_stream, src, pool, pool)); return svn_error_trace(svn_subst_stream_translated_to_normal_form( stream_p, src_stream, eol_style, eol_str, always_repair_eols, keywords, pool)); }
/* Open a file somewhere in the adm area for directory PATH. * First, add the adm subdir as the next component of PATH, then add * each of the varargs (they are char *'s), then add EXTENSION if it * is non-null, then open the resulting file as *STREAM. * * If FLAGS indicates writing, open the file in the adm tmp area. * This means the file will probably need to be renamed from there, * either by passing the sync flag to close_adm_file() later, or with * an explicit call to sync_adm_file(). */ static svn_error_t * open_adm_file(svn_stream_t **stream, const char **selected_path, const char *path, const char *extension, svn_boolean_t for_writing, apr_pool_t *result_pool, apr_pool_t *scratch_pool, ...) { svn_error_t *err; va_list ap; /* If we're writing, always do it to a tmp file. */ if (for_writing) { /* Extend with tmp name. */ va_start(ap, scratch_pool); path = v_extend_with_adm_name(path, extension, TRUE, result_pool, ap); va_end(ap); err = svn_stream_open_writable(stream, path, result_pool, scratch_pool); } else { /* Extend with regular adm name. */ va_start(ap, scratch_pool); path = v_extend_with_adm_name(path, extension, FALSE, result_pool, ap); va_end(ap); err = svn_stream_open_readonly(stream, path, result_pool, scratch_pool); } if (selected_path) *selected_path = path; /* note: built in result_pool */ if (for_writing && err && APR_STATUS_IS_EEXIST(err->apr_err)) { /* Exclusive open failed, delete and retry */ svn_error_clear(err); SVN_ERR(svn_io_remove_file(path, scratch_pool)); err = svn_stream_open_writable(stream, path, result_pool, scratch_pool); } /* Examine the error from the first and/or second attempt at opening. */ if (for_writing && err && APR_STATUS_IS_ENOENT(err->apr_err)) { /* If we receive a failure to open a file in our temporary directory, * it may be because our temporary directories aren't created. * Older SVN clients did not create these directories. * 'svn cleanup' will fix this problem. */ err = svn_error_quick_wrap(err, _("Your .svn/tmp directory may be missing or " "corrupt; run 'svn cleanup' and try again")); } return err; }
svn_error_t * svn_wc__open_adm_stream(svn_stream_t **stream, const char *dir_abspath, const char *fname, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *local_abspath; SVN_ERR_ASSERT(svn_dirent_is_absolute(dir_abspath)); local_abspath = svn_wc__adm_child(dir_abspath, fname, scratch_pool); return svn_error_trace(svn_stream_open_readonly(stream, local_abspath, result_pool, scratch_pool)); }
svn_error_t * svn_wc__get_revert_contents(svn_stream_t **contents, const char *path, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *revert_base = svn_wc__text_revert_path(path, scratch_pool); if (revert_base == NULL) { *contents = NULL; return SVN_NO_ERROR; } return svn_stream_open_readonly(contents, revert_base, result_pool, scratch_pool); }
svn_error_t * svn_config_read_auth_data(apr_hash_t **hash, const char *cred_kind, const char *realmstring, const char *config_dir, apr_pool_t *pool) { svn_node_kind_t kind; const char *auth_path; *hash = NULL; SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir, pool)); if (! auth_path) return SVN_NO_ERROR; SVN_ERR(svn_io_check_path(auth_path, &kind, pool)); if (kind == svn_node_file) { svn_stream_t *stream; svn_string_t *stored_realm; SVN_ERR_W(svn_stream_open_readonly(&stream, auth_path, pool, pool), _("Unable to open auth file for reading")); *hash = apr_hash_make(pool); SVN_ERR_W(svn_hash_read2(*hash, stream, SVN_HASH_TERMINATOR, pool), apr_psprintf(pool, _("Error parsing '%s'"), svn_dirent_local_style(auth_path, pool))); stored_realm = svn_hash_gets(*hash, SVN_CONFIG_REALMSTRING_KEY); if (!stored_realm || strcmp(stored_realm->data, realmstring) != 0) *hash = NULL; /* Hash collision, or somebody tampering with storage */ SVN_ERR(svn_stream_close(stream)); } return SVN_NO_ERROR; }
static svn_error_t * test_stream_interface(const svn_test_opts_t *opts, apr_pool_t *pool) { svn_config_t *cfg; const char *cfg_file; svn_stream_t *stream; SVN_ERR(get_config_file_path(&cfg_file, opts, pool)); SVN_ERR(svn_stream_open_readonly(&stream, cfg_file, pool, pool)); SVN_ERR(svn_config_parse(&cfg, stream, TRUE, TRUE, pool)); /* nominal test to make sure cfg is populated with something since * svn_config_parse will happily return an empty cfg if the stream is * empty. */ if (! svn_config_has_section(cfg, "section1")) return fail(pool, "Failed to find section1"); return SVN_NO_ERROR; }
static svn_error_t * file_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *result_pool, svn_txdelta_window_handler_t *handler, void **handler_baton) { struct file_baton_t *fb = file_baton; const char *target_dir = svn_dirent_dirname(fb->local_abspath, fb->pool); svn_error_t *err; svn_stream_t *source; svn_stream_t *target; SVN_ERR_ASSERT(! fb->writing_file); err = svn_stream_open_readonly(&source, fb->local_abspath, fb->pool, fb->pool); if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); source = svn_stream_empty(fb->pool); } else SVN_ERR(err); SVN_ERR(svn_stream_open_unique(&target, &fb->writing_file, target_dir, svn_io_file_del_none, fb->pool, fb->pool)); svn_txdelta_apply(source, target, fb->digest, fb->local_abspath, fb->pool, /* Provide the handler directly */ handler, handler_baton); return SVN_NO_ERROR; }
svn_error_t * svn_config_read_auth_data(apr_hash_t **hash, const char *cred_kind, const char *realmstring, const char *config_dir, apr_pool_t *pool) { svn_node_kind_t kind; const char *auth_path; *hash = NULL; SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir, pool)); if (! auth_path) return SVN_NO_ERROR; SVN_ERR(svn_io_check_path(auth_path, &kind, pool)); if (kind == svn_node_file) { svn_stream_t *stream; SVN_ERR_W(svn_stream_open_readonly(&stream, auth_path, pool, pool), _("Unable to open auth file for reading")); *hash = apr_hash_make(pool); SVN_ERR_W(svn_hash_read2(*hash, stream, SVN_HASH_TERMINATOR, pool), apr_psprintf(pool, _("Error parsing '%s'"), svn_dirent_local_style(auth_path, pool))); SVN_ERR(svn_stream_close(stream)); } return SVN_NO_ERROR; }
svn_error_t * svn_client_blame5(const char *target, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *start, const svn_opt_revision_t *end, const svn_diff_file_options_t *diff_options, svn_boolean_t ignore_mime_type, svn_boolean_t include_merged_revisions, svn_client_blame_receiver3_t receiver, void *receiver_baton, svn_client_ctx_t *ctx, apr_pool_t *pool) { struct file_rev_baton frb; svn_ra_session_t *ra_session; svn_revnum_t start_revnum, end_revnum; struct blame *walk, *walk_merged = NULL; apr_pool_t *iterpool; svn_stream_t *last_stream; svn_stream_t *stream; const char *target_abspath_or_url; if (start->kind == svn_opt_revision_unspecified || end->kind == svn_opt_revision_unspecified) return svn_error_create (SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL); if (svn_path_is_url(target)) target_abspath_or_url = target; else SVN_ERR(svn_dirent_get_absolute(&target_abspath_or_url, target, pool)); /* Get an RA plugin for this filesystem object. */ SVN_ERR(svn_client__ra_session_from_path(&ra_session, &end_revnum, NULL, target, NULL, peg_revision, end, ctx, pool)); SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx, target_abspath_or_url, ra_session, start, pool)); if (end_revnum < start_revnum) return svn_error_create (SVN_ERR_CLIENT_BAD_REVISION, NULL, _("Start revision must precede end revision")); frb.start_rev = start_revnum; frb.end_rev = end_revnum; frb.target = target; frb.ctx = ctx; frb.diff_options = diff_options; frb.ignore_mime_type = ignore_mime_type; frb.include_merged_revisions = include_merged_revisions; frb.last_filename = NULL; frb.last_original_filename = NULL; frb.chain = apr_palloc(pool, sizeof(*frb.chain)); frb.chain->blame = NULL; frb.chain->avail = NULL; frb.chain->pool = pool; if (include_merged_revisions) { frb.merged_chain = apr_palloc(pool, sizeof(*frb.merged_chain)); frb.merged_chain->blame = NULL; frb.merged_chain->avail = NULL; frb.merged_chain->pool = pool; } SVN_ERR(svn_ra_get_repos_root2(ra_session, &frb.repos_root_url, pool)); frb.mainpool = pool; /* The callback will flip the following two pools, because it needs information from the previous call. Obviously, it can't rely on the lifetime of the pool provided by get_file_revs. */ frb.lastpool = svn_pool_create(pool); frb.currpool = svn_pool_create(pool); if (include_merged_revisions) { frb.filepool = svn_pool_create(pool); frb.prevfilepool = svn_pool_create(pool); } /* Collect all blame information. We need to ensure that we get one revision before the start_rev, if available so that we can know what was actually changed in the start revision. */ SVN_ERR(svn_ra_get_file_revs2(ra_session, "", start_revnum - (start_revnum > 0 ? 1 : 0), end_revnum, include_merged_revisions, file_rev_handler, &frb, pool)); if (end->kind == svn_opt_revision_working) { /* If the local file is modified we have to call the handler on the working copy file with keywords unexpanded */ svn_wc_status3_t *status; SVN_ERR(svn_wc_status3(&status, ctx->wc_ctx, target_abspath_or_url, pool, pool)); if (status->text_status != svn_wc_status_normal) { apr_hash_t *props; svn_stream_t *wcfile; svn_string_t *keywords; svn_stream_t *tempfile; const char *temppath; apr_hash_t *kw = NULL; SVN_ERR(svn_wc_prop_list2(&props, ctx->wc_ctx, target_abspath_or_url, pool, pool)); SVN_ERR(svn_stream_open_readonly(&wcfile, target, pool, pool)); keywords = apr_hash_get(props, SVN_PROP_KEYWORDS, APR_HASH_KEY_STRING); if (keywords) SVN_ERR(svn_subst_build_keywords2(&kw, keywords->data, NULL, NULL, 0, NULL, pool)); wcfile = svn_subst_stream_translated(wcfile, "\n", TRUE, kw, FALSE, pool); SVN_ERR(svn_stream_open_unique(&tempfile, &temppath, NULL, svn_io_file_del_on_pool_cleanup, pool, pool)); SVN_ERR(svn_stream_copy3(wcfile, tempfile, ctx->cancel_func, ctx->cancel_baton, pool)); SVN_ERR(add_file_blame(frb.last_filename, temppath, frb.chain, NULL, frb.diff_options, pool)); frb.last_filename = temppath; } } /* Report the blame to the caller. */ /* The callback has to have been called at least once. */ SVN_ERR_ASSERT(frb.last_filename != NULL); /* Create a pool for the iteration below. */ iterpool = svn_pool_create(pool); /* Open the last file and get a stream. */ SVN_ERR(svn_stream_open_readonly(&last_stream, frb.last_filename, pool, pool)); stream = svn_subst_stream_translated(last_stream, "\n", TRUE, NULL, FALSE, pool); /* Perform optional merged chain normalization. */ if (include_merged_revisions) { /* If we never created any blame for the original chain, create it now, with the most recent changed revision. This could occur if a file was created on a branch and them merged to another branch. This is semanticly a copy, and we want to use the revision on the branch as the most recently changed revision. ### Is this really what we want to do here? Do the sematics of copy change? */ if (!frb.chain->blame) frb.chain->blame = blame_create(frb.chain, frb.rev, 0); normalize_blames(frb.chain, frb.merged_chain, pool); walk_merged = frb.merged_chain->blame; } /* Process each blame item. */ for (walk = frb.chain->blame; walk; walk = walk->next) { apr_off_t line_no; svn_revnum_t merged_rev; const char *merged_path; apr_hash_t *merged_rev_props; if (walk_merged) { merged_rev = walk_merged->rev->revision; merged_rev_props = walk_merged->rev->rev_props; merged_path = walk_merged->rev->path; } else { merged_rev = SVN_INVALID_REVNUM; merged_rev_props = NULL; merged_path = NULL; } for (line_no = walk->start; !walk->next || line_no < walk->next->start; ++line_no) { svn_boolean_t eof; svn_stringbuf_t *sb; svn_pool_clear(iterpool); SVN_ERR(svn_stream_readline(stream, &sb, "\n", &eof, iterpool)); if (ctx->cancel_func) SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); if (!eof || sb->len) { if (walk->rev) SVN_ERR(receiver(receiver_baton, start_revnum, end_revnum, line_no, walk->rev->revision, walk->rev->rev_props, merged_rev, merged_rev_props, merged_path, sb->data, FALSE, iterpool)); else SVN_ERR(receiver(receiver_baton, start_revnum, end_revnum, line_no, SVN_INVALID_REVNUM, NULL, SVN_INVALID_REVNUM, NULL, NULL, sb->data, TRUE, iterpool)); } if (eof) break; } if (walk_merged) walk_merged = walk_merged->next; } SVN_ERR(svn_stream_close(stream)); svn_pool_destroy(frb.lastpool); svn_pool_destroy(frb.currpool); if (include_merged_revisions) { svn_pool_destroy(frb.filepool); svn_pool_destroy(frb.prevfilepool); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }
static svn_error_t * file_rev_handler(void *baton, const char *path, svn_revnum_t revnum, apr_hash_t *rev_props, svn_boolean_t merged_revision, svn_txdelta_window_handler_t *content_delta_handler, void **content_delta_baton, apr_array_header_t *prop_diffs, apr_pool_t *pool) { struct file_rev_baton *frb = baton; svn_stream_t *last_stream; svn_stream_t *cur_stream; struct delta_baton *delta_baton; apr_pool_t *filepool; /* Clear the current pool. */ svn_pool_clear(frb->currpool); /* If this file has a non-textual mime-type, bail out. */ if (! frb->ignore_mime_type) SVN_ERR(check_mimetype(prop_diffs, frb->target, frb->currpool)); if (frb->ctx->notify_func2) { svn_wc_notify_t *notify = svn_wc_create_notify_url( svn_path_url_add_component2(frb->repos_root_url, path+1, pool), svn_wc_notify_blame_revision, pool); notify->path = path; notify->kind = svn_node_none; notify->content_state = notify->prop_state = svn_wc_notify_state_inapplicable; notify->lock_state = svn_wc_notify_lock_state_inapplicable; notify->revision = revnum; notify->rev_props = rev_props; frb->ctx->notify_func2(frb->ctx->notify_baton2, notify, pool); } if (frb->ctx->cancel_func) SVN_ERR(frb->ctx->cancel_func(frb->ctx->cancel_baton)); /* If there were no content changes, we couldn't care less about this revision now. Note that we checked the mime type above, so things work if the user just changes the mime type in a commit. Also note that we don't switch the pools in this case. This is important, since the tempfile will be removed by the pool and we need the tempfile from the last revision with content changes. */ if (!content_delta_handler) return SVN_NO_ERROR; frb->merged_revision = merged_revision; /* Create delta baton. */ delta_baton = apr_palloc(frb->currpool, sizeof(*delta_baton)); /* Prepare the text delta window handler. */ if (frb->last_filename) SVN_ERR(svn_stream_open_readonly(&delta_baton->source_stream, frb->last_filename, frb->currpool, pool)); else /* Means empty stream below. */ delta_baton->source_stream = NULL; last_stream = svn_stream_disown(delta_baton->source_stream, pool); if (frb->include_merged_revisions && !frb->merged_revision) filepool = frb->filepool; else filepool = frb->currpool; SVN_ERR(svn_stream_open_unique(&cur_stream, &delta_baton->filename, NULL, svn_io_file_del_on_pool_cleanup, filepool, filepool)); /* Get window handler for applying delta. */ svn_txdelta_apply(last_stream, cur_stream, NULL, NULL, frb->currpool, &delta_baton->wrapped_handler, &delta_baton->wrapped_baton); /* Wrap the window handler with our own. */ delta_baton->file_rev_baton = frb; *content_delta_handler = window_handler; *content_delta_baton = delta_baton; /* Create the rev structure. */ frb->rev = apr_pcalloc(frb->mainpool, sizeof(struct rev)); if (revnum < frb->start_rev) { /* We shouldn't get more than one revision before the starting revision (unless of including merged revisions). */ SVN_ERR_ASSERT((frb->last_filename == NULL) || frb->include_merged_revisions); /* The file existed before start_rev; generate no blame info for lines from this revision (or before). */ frb->rev->revision = SVN_INVALID_REVNUM; } else { SVN_ERR_ASSERT(revnum <= frb->end_rev); /* Set values from revision props. */ frb->rev->revision = revnum; frb->rev->rev_props = svn_prop_hash_dup(rev_props, frb->mainpool); } if (frb->include_merged_revisions) frb->rev->path = apr_pstrdup(frb->mainpool, path); return SVN_NO_ERROR; }
/* Parse the file at DIGEST_PATH, populating the lock LOCK_P in that file (if it exists, and if *LOCK_P is non-NULL) and the hash of CHILDREN_P (if any exist, and if *CHILDREN_P is non-NULL). Use POOL for all allocations. */ static svn_error_t * read_digest_file(apr_hash_t **children_p, svn_lock_t **lock_p, const char *fs_path, const char *digest_path, apr_pool_t *pool) { svn_error_t *err = SVN_NO_ERROR; svn_lock_t *lock; apr_hash_t *hash; svn_stream_t *stream; const char *val; if (lock_p) *lock_p = NULL; if (children_p) *children_p = apr_hash_make(pool); err = svn_stream_open_readonly(&stream, digest_path, pool, pool); if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); return SVN_NO_ERROR; } SVN_ERR(err); /* If our caller doesn't care about anything but the presence of the file... whatever. */ if (! (lock_p || children_p)) return svn_stream_close(stream); hash = apr_hash_make(pool); if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool))) { svn_error_clear(svn_stream_close(stream)); return svn_error_createf(err->apr_err, err, _("Can't parse lock/entries hashfile '%s'"), svn_dirent_local_style(digest_path, pool)); } SVN_ERR(svn_stream_close(stream)); /* If our caller cares, see if we have a lock path in our hash. If so, we'll assume we have a lock here. */ val = hash_fetch(hash, PATH_KEY, pool); if (val && lock_p) { const char *path = val; /* Create our lock and load it up. */ lock = svn_lock_create(pool); lock->path = path; if (! ((lock->token = hash_fetch(hash, TOKEN_KEY, pool)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); if (! ((lock->owner = hash_fetch(hash, OWNER_KEY, pool)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); if (! ((val = hash_fetch(hash, IS_DAV_COMMENT_KEY, pool)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); lock->is_dav_comment = (val[0] == '1'); if (! ((val = hash_fetch(hash, CREATION_DATE_KEY, pool)))) return svn_error_trace(err_corrupt_lockfile(fs_path, path)); SVN_ERR(svn_time_from_cstring(&(lock->creation_date), val, pool)); if ((val = hash_fetch(hash, EXPIRATION_DATE_KEY, pool))) SVN_ERR(svn_time_from_cstring(&(lock->expiration_date), val, pool)); lock->comment = hash_fetch(hash, COMMENT_KEY, pool); *lock_p = lock; } /* If our caller cares, see if we have any children for this path. */ val = hash_fetch(hash, CHILDREN_KEY, pool); if (val && children_p) { apr_array_header_t *kiddos = svn_cstring_split(val, "\n", FALSE, pool); int i; for (i = 0; i < kiddos->nelts; i++) { apr_hash_set(*children_p, APR_ARRAY_IDX(kiddos, i, const char *), APR_HASH_KEY_STRING, (void *)1); } }
svn_error_t * svn_config_walk_auth_data(const char *config_dir, svn_config_auth_walk_func_t walk_func, void *walk_baton, apr_pool_t *scratch_pool) { int i; apr_pool_t *iterpool; svn_boolean_t finished = FALSE; const char *cred_kinds[] = { SVN_AUTH_CRED_SIMPLE, SVN_AUTH_CRED_USERNAME, SVN_AUTH_CRED_SSL_CLIENT_CERT, SVN_AUTH_CRED_SSL_CLIENT_CERT_PW, SVN_AUTH_CRED_SSL_SERVER_TRUST, NULL }; iterpool = svn_pool_create(scratch_pool); for (i = 0; cred_kinds[i]; i++) { const char *item_path; const char *dir_path; apr_hash_t *nodes; svn_error_t *err; apr_pool_t *itempool; apr_hash_index_t *hi; svn_pool_clear(iterpool); if (finished) break; SVN_ERR(svn_auth__file_path(&item_path, cred_kinds[i], "!", config_dir, iterpool)); dir_path = svn_dirent_dirname(item_path, iterpool); err = svn_io_get_dirents3(&nodes, dir_path, TRUE, iterpool, iterpool); if (err) { if (!APR_STATUS_IS_ENOENT(err->apr_err) && !SVN__APR_STATUS_IS_ENOTDIR(err->apr_err)) return svn_error_trace(err); svn_error_clear(err); continue; } itempool = svn_pool_create(iterpool); for (hi = apr_hash_first(iterpool, nodes); hi; hi = apr_hash_next(hi)) { svn_io_dirent2_t *dirent = apr_hash_this_val(hi); svn_stream_t *stream; apr_hash_t *creds_hash; const svn_string_t *realm; svn_boolean_t delete_file = FALSE; if (finished) break; if (dirent->kind != svn_node_file) continue; svn_pool_clear(itempool); item_path = svn_dirent_join(dir_path, apr_hash_this_key(hi), itempool); err = svn_stream_open_readonly(&stream, item_path, itempool, itempool); if (err) { /* Ignore this file. There are no credentials in it anyway */ svn_error_clear(err); continue; } creds_hash = apr_hash_make(itempool); err = svn_hash_read2(creds_hash, stream, SVN_HASH_TERMINATOR, itempool); err = svn_error_compose_create(err, svn_stream_close(stream)); if (err) { /* Ignore this file. There are no credentials in it anyway */ svn_error_clear(err); continue; } realm = svn_hash_gets(creds_hash, SVN_CONFIG_REALMSTRING_KEY); if (! realm) continue; /* Not an auth file */ err = walk_func(&delete_file, walk_baton, cred_kinds[i], realm->data, creds_hash, itempool); if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION) { svn_error_clear(err); err = SVN_NO_ERROR; finished = TRUE; } SVN_ERR(err); if (delete_file) { /* Delete the file on disk */ SVN_ERR(svn_io_remove_file2(item_path, TRUE, itempool)); } } } svn_pool_destroy(iterpool); return SVN_NO_ERROR; }
svn_error_t * svn_wc__internal_translated_stream(svn_stream_t **stream, svn_wc__db_t *db, const char *local_abspath, const char *versioned_abspath, apr_uint32_t flags, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_boolean_t special; svn_boolean_t to_nf = flags & SVN_WC_TRANSLATE_TO_NF; svn_subst_eol_style_t style; const char *eol; apr_hash_t *keywords; svn_boolean_t repair_forced = flags & SVN_WC_TRANSLATE_FORCE_EOL_REPAIR; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_abspath)); SVN_ERR(svn_wc__get_translate_info(&style, &eol, &keywords, &special, db, versioned_abspath, NULL, FALSE, scratch_pool, scratch_pool)); if (special) { if (to_nf) return svn_subst_read_specialfile(stream, local_abspath, result_pool, scratch_pool); return svn_subst_create_specialfile(stream, local_abspath, result_pool, scratch_pool); } if (to_nf) SVN_ERR(svn_stream_open_readonly(stream, local_abspath, result_pool, scratch_pool)); else { apr_file_t *file; /* We don't want the "open-exclusively" feature of the normal svn_stream_open_writable interface. Do this manually. */ SVN_ERR(svn_io_file_open(&file, local_abspath, APR_CREATE | APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, result_pool)); *stream = svn_stream_from_aprfile2(file, FALSE, result_pool); } if (svn_subst_translation_required(style, eol, keywords, special, TRUE)) { if (to_nf) { if (style == svn_subst_eol_style_native) eol = SVN_SUBST_NATIVE_EOL_STR; else if (style == svn_subst_eol_style_fixed) repair_forced = TRUE; else if (style != svn_subst_eol_style_none) return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL); /* Wrap the stream to translate to normal form */ *stream = svn_subst_stream_translated(*stream, eol, repair_forced, keywords, FALSE /* expand */, result_pool); /* Enforce our contract. TO_NF streams are readonly */ svn_stream_set_write(*stream, write_handler_unsupported); } else { *stream = svn_subst_stream_translated(*stream, eol, TRUE, keywords, TRUE, result_pool); /* Enforce our contract. FROM_NF streams are write-only */ svn_stream_set_read(*stream, read_handler_unsupported); } } return SVN_NO_ERROR; }
/* Produce a diff between two arbitrary files at LOCAL_ABSPATH1 and * LOCAL_ABSPATH2, using the diff callbacks from CALLBACKS. * Use PATH as the name passed to diff callbacks. * FILE1_IS_EMPTY and FILE2_IS_EMPTY are used as hints which diff callback * function to use to compare the files (added/deleted/changed). * * If ORIGINAL_PROPS_OVERRIDE is not NULL, use it as original properties * instead of reading properties from LOCAL_ABSPATH1. This is required when * a file replaces a directory, where LOCAL_ABSPATH1 is an empty file that * file content must be diffed against, but properties to diff against come * from the replaced directory. */ static svn_error_t * do_arbitrary_files_diff(const char *local_abspath1, const char *local_abspath2, const char *path, svn_boolean_t file1_is_empty, svn_boolean_t file2_is_empty, apr_hash_t *original_props_override, const svn_wc_diff_callbacks4_t *callbacks, void *diff_baton, svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { apr_hash_t *original_props; apr_hash_t *modified_props; apr_array_header_t *prop_changes; svn_string_t *original_mime_type = NULL; svn_string_t *modified_mime_type = NULL; if (ctx->cancel_func) SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); /* Try to get properties from either file. It's OK if the files do not * have properties, or if they are unversioned. */ if (original_props_override) original_props = original_props_override; else SVN_ERR(get_props(&original_props, local_abspath1, ctx->wc_ctx, scratch_pool, scratch_pool)); SVN_ERR(get_props(&modified_props, local_abspath2, ctx->wc_ctx, scratch_pool, scratch_pool)); SVN_ERR(svn_prop_diffs(&prop_changes, modified_props, original_props, scratch_pool)); /* Try to determine the mime-type of each file. */ original_mime_type = svn_hash_gets(original_props, SVN_PROP_MIME_TYPE); if (!file1_is_empty && !original_mime_type) { const char *mime_type; SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1, ctx->mimetypes_map, scratch_pool)); if (mime_type) original_mime_type = svn_string_create(mime_type, scratch_pool); } modified_mime_type = svn_hash_gets(modified_props, SVN_PROP_MIME_TYPE); if (!file2_is_empty && !modified_mime_type) { const char *mime_type; SVN_ERR(svn_io_detect_mimetype2(&mime_type, local_abspath1, ctx->mimetypes_map, scratch_pool)); if (mime_type) modified_mime_type = svn_string_create(mime_type, scratch_pool); } /* Produce the diff. */ if (file1_is_empty && !file2_is_empty) SVN_ERR(callbacks->file_added(NULL, NULL, NULL, path, local_abspath1, local_abspath2, /* ### TODO get real revision info * for versioned files? */ SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, original_mime_type ? original_mime_type->data : NULL, modified_mime_type ? modified_mime_type->data : NULL, /* ### TODO get copyfrom? */ NULL, SVN_INVALID_REVNUM, prop_changes, original_props, diff_baton, scratch_pool)); else if (!file1_is_empty && file2_is_empty) SVN_ERR(callbacks->file_deleted(NULL, NULL, path, local_abspath1, local_abspath2, original_mime_type ? original_mime_type->data : NULL, modified_mime_type ? modified_mime_type->data : NULL, original_props, diff_baton, scratch_pool)); else { svn_stream_t *file1; svn_stream_t *file2; svn_boolean_t same; svn_string_t *val; /* We have two files, which may or may not be the same. ### Our caller assumes that we should ignore symlinks here and handle them as normal paths. Perhaps that should change? */ SVN_ERR(svn_stream_open_readonly(&file1, local_abspath1, scratch_pool, scratch_pool)); SVN_ERR(svn_stream_open_readonly(&file2, local_abspath2, scratch_pool, scratch_pool)); /* Wrap with normalization, etc. if necessary */ if (original_props) { val = svn_hash_gets(original_props, SVN_PROP_EOL_STYLE); if (val) { svn_subst_eol_style_t style; const char *eol; svn_subst_eol_style_from_value(&style, &eol, val->data); /* ### Ignoring keywords */ if (eol) file1 = svn_subst_stream_translated(file1, eol, TRUE, NULL, FALSE, scratch_pool); } } if (modified_props) { val = svn_hash_gets(modified_props, SVN_PROP_EOL_STYLE); if (val) { svn_subst_eol_style_t style; const char *eol; svn_subst_eol_style_from_value(&style, &eol, val->data); /* ### Ignoring keywords */ if (eol) file2 = svn_subst_stream_translated(file2, eol, TRUE, NULL, FALSE, scratch_pool); } } SVN_ERR(svn_stream_contents_same2(&same, file1, file2, scratch_pool)); if (! same || prop_changes->nelts > 0) { /* ### We should probably pass the normalized data we created using the subst streams as that is what diff users expect */ SVN_ERR(callbacks->file_changed(NULL, NULL, NULL, path, same ? NULL : local_abspath1, same ? NULL : local_abspath2, /* ### TODO get real revision info * for versioned files? */ SVN_INVALID_REVNUM /* rev1 */, SVN_INVALID_REVNUM /* rev2 */, original_mime_type ? original_mime_type->data : NULL, modified_mime_type ? modified_mime_type->data : NULL, prop_changes, original_props, diff_baton, scratch_pool)); } } return SVN_NO_ERROR; }
/* Handle the moving of a pristine from SRC_WCROOT to DST_WCROOT. The existing pristine in SRC_WCROOT is described by CHECKSUM, MD5_CHECKSUM and SIZE */ static svn_error_t * maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot, svn_wc__db_wcroot_t *dst_wcroot, const svn_checksum_t *checksum, const svn_checksum_t *md5_checksum, apr_int64_t size, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { const char *pristine_abspath; svn_sqlite__stmt_t *stmt; svn_stream_t *src_stream; svn_stream_t *dst_stream; const char *tmp_abspath; const char *src_abspath; int affected_rows; svn_error_t *err; SVN_ERR(svn_sqlite__get_statement(&stmt, dst_wcroot->sdb, STMT_INSERT_OR_IGNORE_PRISTINE)); SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, checksum, scratch_pool)); SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool)); SVN_ERR(svn_sqlite__bind_int64(stmt, 3, size)); SVN_ERR(svn_sqlite__update(&affected_rows, stmt)); if (affected_rows == 0) return SVN_NO_ERROR; SVN_ERR(svn_stream_open_unique(&dst_stream, &tmp_abspath, pristine_get_tempdir(dst_wcroot, scratch_pool, scratch_pool), svn_io_file_del_on_pool_cleanup, scratch_pool, scratch_pool)); SVN_ERR(get_pristine_fname(&src_abspath, src_wcroot->abspath, checksum, scratch_pool, scratch_pool)); SVN_ERR(svn_stream_open_readonly(&src_stream, src_abspath, scratch_pool, scratch_pool)); /* ### Should we verify the SHA1 or MD5 here, or is that too expensive? */ SVN_ERR(svn_stream_copy3(src_stream, dst_stream, cancel_func, cancel_baton, scratch_pool)); SVN_ERR(get_pristine_fname(&pristine_abspath, dst_wcroot->abspath, checksum, scratch_pool, scratch_pool)); /* Move the file to its target location. (If it is already there, it is * an orphan file and it doesn't matter if we overwrite it.) */ err = svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE, scratch_pool); /* Maybe the directory doesn't exist yet? */ if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_t *err2; err2 = svn_io_dir_make(svn_dirent_dirname(pristine_abspath, scratch_pool), APR_OS_DEFAULT, scratch_pool); if (err2) /* Creating directory didn't work: Return all errors */ return svn_error_trace(svn_error_compose_create(err, err2)); else /* We could create a directory: retry install */ svn_error_clear(err); SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE, scratch_pool)); } else SVN_ERR(err); return SVN_NO_ERROR; }
svn_error_t * svn_client__get_normalized_stream(svn_stream_t **normal_stream, svn_wc_context_t *wc_ctx, const char *local_abspath, const svn_opt_revision_t *revision, svn_boolean_t expand_keywords, svn_boolean_t normalize_eols, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_hash_t *kw = NULL; svn_subst_eol_style_t style; apr_hash_t *props; svn_string_t *eol_style, *keywords, *special; const char *eol = NULL; svn_boolean_t local_mod = FALSE; apr_time_t tm; svn_stream_t *input; svn_node_kind_t kind; SVN_ERR_ASSERT(SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind)); SVN_ERR(svn_wc_read_kind(&kind, wc_ctx, local_abspath, FALSE, scratch_pool)); if (kind == svn_node_unknown || kind == svn_node_none) return svn_error_createf(SVN_ERR_UNVERSIONED_RESOURCE, NULL, _("'%s' is not under version control"), svn_dirent_local_style(local_abspath, scratch_pool)); if (kind != svn_node_file) return svn_error_createf(SVN_ERR_CLIENT_IS_DIRECTORY, NULL, _("'%s' refers to a directory"), svn_dirent_local_style(local_abspath, scratch_pool)); if (revision->kind != svn_opt_revision_working) { SVN_ERR(svn_wc_get_pristine_contents2(&input, wc_ctx, local_abspath, result_pool, scratch_pool)); if (input == NULL) return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, _("'%s' has no base revision until it is committed"), svn_dirent_local_style(local_abspath, scratch_pool)); SVN_ERR(svn_wc_get_pristine_props(&props, wc_ctx, local_abspath, scratch_pool, scratch_pool)); } else { svn_wc_status3_t *status; SVN_ERR(svn_stream_open_readonly(&input, local_abspath, scratch_pool, result_pool)); SVN_ERR(svn_wc_prop_list2(&props, wc_ctx, local_abspath, scratch_pool, scratch_pool)); SVN_ERR(svn_wc_status3(&status, wc_ctx, local_abspath, scratch_pool, scratch_pool)); if (status->text_status != svn_wc_status_normal) local_mod = TRUE; } eol_style = apr_hash_get(props, SVN_PROP_EOL_STYLE, APR_HASH_KEY_STRING); keywords = apr_hash_get(props, SVN_PROP_KEYWORDS, APR_HASH_KEY_STRING); special = apr_hash_get(props, SVN_PROP_SPECIAL, APR_HASH_KEY_STRING); if (eol_style) svn_subst_eol_style_from_value(&style, &eol, eol_style->data); if (local_mod && (! special)) { /* Use the modified time from the working copy if the file */ SVN_ERR(svn_io_file_affected_time(&tm, local_abspath, scratch_pool)); } else { SVN_ERR(svn_wc__node_get_changed_info(NULL, &tm, NULL, wc_ctx, local_abspath, scratch_pool, scratch_pool)); } if (keywords) { svn_revnum_t changed_rev; const char *rev_str; const char *author; const char *url; SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, NULL, &author, wc_ctx, local_abspath, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, local_abspath, scratch_pool, scratch_pool)); if (local_mod) { /* For locally modified files, we'll append an 'M' to the revision number, and set the author to "(local)" since we can't always determine the current user's username */ rev_str = apr_psprintf(scratch_pool, "%ldM", changed_rev); author = _("(local)"); } else { rev_str = apr_psprintf(scratch_pool, "%ld", changed_rev); } SVN_ERR(svn_subst_build_keywords2(&kw, keywords->data, rev_str, url, tm, author, scratch_pool)); } /* Wrap the output stream if translation is needed. */ if (eol != NULL || kw != NULL) input = svn_subst_stream_translated( input, (eol_style && normalize_eols) ? SVN_SUBST_NATIVE_EOL_STR : eol, FALSE, kw, expand_keywords, result_pool); *normal_stream = input; return SVN_NO_ERROR; }
/* An svn_delta_editor_t function. */ static svn_error_t * apply_textdelta(void *file_baton, const char *base_md5_digest, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **handler_baton) { struct file_baton *b = file_baton; svn_stream_t *src_stream; svn_stream_t *result_stream; apr_pool_t *scratch_pool = b->pool; /* Skip *everything* within a newly tree-conflicted directory. */ if (b->skip) { *handler = svn_delta_noop_window_handler; *handler_baton = NULL; return SVN_NO_ERROR; } /* If we're not sending file text, then ignore any that we receive. */ if (! b->edit_baton->text_deltas) { /* Supply valid paths to indicate there is a text change. */ SVN_ERR(get_empty_file(b->edit_baton, &b->path_start_revision)); SVN_ERR(get_empty_file(b->edit_baton, &b->path_end_revision)); *handler = svn_delta_noop_window_handler; *handler_baton = NULL; return SVN_NO_ERROR; } /* We need the expected pristine file, so go get it */ if (!b->added) SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool)); else SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision))); SVN_ERR_ASSERT(b->path_start_revision != NULL); if (base_md5_digest != NULL) { svn_checksum_t *base_md5_checksum; SVN_ERR(svn_checksum_parse_hex(&base_md5_checksum, svn_checksum_md5, base_md5_digest, scratch_pool)); if (!svn_checksum_match(base_md5_checksum, b->start_md5_checksum)) return svn_error_trace(svn_checksum_mismatch_err( base_md5_checksum, b->start_md5_checksum, scratch_pool, _("Base checksum mismatch for '%s'"), b->path)); } /* Open the file to be used as the base for second revision */ SVN_ERR(svn_stream_open_readonly(&src_stream, b->path_start_revision, scratch_pool, scratch_pool)); /* Open the file that will become the second revision after applying the text delta, it starts empty */ SVN_ERR(svn_stream_open_unique(&result_stream, &b->path_end_revision, NULL, svn_io_file_del_on_pool_cleanup, scratch_pool, scratch_pool)); svn_txdelta_apply(src_stream, result_stream, b->result_digest, b->path, b->pool, &(b->apply_handler), &(b->apply_baton)); *handler = window_handler; *handler_baton = file_baton; return SVN_NO_ERROR; }