svn_error_t * OperationContext::openTunnel(svn_stream_t **request, svn_stream_t **response, svn_ra_close_tunnel_func_t *close_func, void **close_baton, void *tunnel_baton, const char *tunnel_name, const char *user, const char *hostname, int port, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { TunnelContext *tc = new TunnelContext(pool); if (tc->status) { delete tc; return svn_error_trace( svn_error_wrap_apr(tc->status, _("Could not open tunnel streams"))); } *close_func = closeTunnel; *close_baton = tc; *request = svn_stream_from_aprfile2(tc->request_out, FALSE, pool); *response = svn_stream_from_aprfile2(tc->response_in, FALSE, pool); JNIEnv *env = JNIUtil::getEnv(); jobject jrequest = create_RequestChannel(env, tc->request_in); SVN_JNI_CATCH(, SVN_ERR_BASE); jobject jresponse = create_ResponseChannel(env, tc->response_out); SVN_JNI_CATCH(, SVN_ERR_BASE); jstring jtunnel_name = JNIUtil::makeJString(tunnel_name); SVN_JNI_CATCH(, SVN_ERR_BASE); jstring juser = JNIUtil::makeJString(user); SVN_JNI_CATCH(, SVN_ERR_BASE); jstring jhostname = JNIUtil::makeJString(hostname); SVN_JNI_CATCH(, SVN_ERR_BASE); static jmethodID mid = 0; if (0 == mid) { jclass cls = env->FindClass(JAVAHL_CLASS("/callback/TunnelAgent")); SVN_JNI_CATCH(, SVN_ERR_BASE); SVN_JNI_CATCH( mid = env->GetMethodID( cls, "openTunnel", "(Ljava/nio/channels/ReadableByteChannel;" "Ljava/nio/channels/WritableByteChannel;" "Ljava/lang/String;" "Ljava/lang/String;" "Ljava/lang/String;I)" JAVAHL_ARG("/callback/TunnelAgent$CloseTunnelCallback;")), SVN_ERR_BASE); }
svn_error_t * svn_diff_output_binary(svn_stream_t *output_stream, svn_stream_t *original, svn_stream_t *latest, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { apr_file_t *original_apr; svn_filesize_t original_full; svn_filesize_t original_deflated; apr_file_t *latest_apr; svn_filesize_t latest_full; svn_filesize_t latest_deflated; apr_pool_t *subpool = svn_pool_create(scratch_pool); SVN_ERR(create_compressed(&original_apr, &original_full, &original_deflated, original, cancel_func, cancel_baton, scratch_pool, subpool)); svn_pool_clear(subpool); SVN_ERR(create_compressed(&latest_apr, &latest_full, &latest_deflated, latest, cancel_func, cancel_baton, scratch_pool, subpool)); svn_pool_clear(subpool); SVN_ERR(svn_stream_puts(output_stream, "GIT binary patch" APR_EOL_STR)); /* ### git would first calculate if a git-delta latest->original would be shorter than the zipped data. For now lets assume that it is not and just dump the literal data */ SVN_ERR(write_literal(latest_full, svn_stream_from_aprfile2(latest_apr, FALSE, subpool), output_stream, cancel_func, cancel_baton, scratch_pool)); svn_pool_clear(subpool); SVN_ERR(svn_stream_puts(output_stream, APR_EOL_STR)); /* ### git would first calculate if a git-delta original->latest would be shorter than the zipped data. For now lets assume that it is not and just dump the literal data */ SVN_ERR(write_literal(original_full, svn_stream_from_aprfile2(original_apr, FALSE, subpool), output_stream, cancel_func, cancel_baton, scratch_pool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; }
/* Compute the delta between OLDROOT/OLDPATH and NEWROOT/NEWPATH and store it into a new temporary file *TEMPFILE. OLDROOT may be NULL, in which case the delta will be computed against an empty file, as per the svn_fs_get_file_delta_stream docstring. Record the length of the temporary file in *LEN, and rewind the file before returning. */ static svn_error_t * store_delta(apr_file_t **tempfile, svn_filesize_t *len, svn_fs_root_t *oldroot, const char *oldpath, svn_fs_root_t *newroot, const char *newpath, apr_pool_t *pool) { svn_stream_t *temp_stream; apr_off_t offset = 0; svn_txdelta_stream_t *delta_stream; svn_txdelta_window_handler_t wh; void *whb; /* Create a temporary file and open a stream to it. Note that we need the file handle in order to rewind it. */ SVN_ERR(svn_io_open_unique_file3(tempfile, NULL, NULL, svn_io_file_del_on_pool_cleanup, pool, pool)); temp_stream = svn_stream_from_aprfile2(*tempfile, TRUE, pool); /* Compute the delta and send it to the temporary file. */ SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream, oldroot, oldpath, newroot, newpath, pool)); svn_txdelta_to_svndiff2(&wh, &whb, temp_stream, 0, pool); SVN_ERR(svn_txdelta_send_txstream(delta_stream, wh, whb, pool)); /* Get the length of the temporary file and rewind it. */ SVN_ERR(svn_io_file_seek(*tempfile, APR_CUR, &offset, pool)); *len = offset; offset = 0; return svn_io_file_seek(*tempfile, APR_SET, &offset, pool); }
/* Dumps the contents of a file to stdout */ static svn_error_t *delta_cat_file(apr_pool_t *pool, const char *path) { svn_error_t *err; apr_status_t status; apr_file_t *in_file = NULL; svn_stream_t *in, *out; status = apr_file_open(&in_file, path, APR_READ, 0600, pool); if (status) { apr_pool_t *epool = svn_pool_create(NULL); char *errbuf = apr_palloc(epool, ERRBUFFER_SIZE); return svn_error_create(status, NULL, apr_strerror(status, errbuf, ERRBUFFER_SIZE)); } in = svn_stream_from_aprfile2(in_file, FALSE, pool); if ((err = svn_stream_for_stdout(&out, pool))) { svn_stream_close(in); return err; } /* Write contents */ if ((err = svn_stream_copy(in, out, pool))) { svn_stream_close(in); return err; } err = svn_stream_close(in); return SVN_NO_ERROR; }
/* Subversion delta editor callback */ static svn_error_t *de_apply_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **handler_baton) { apr_file_t *src_file = NULL, *dest_file = NULL; svn_stream_t *src_stream, *dest_stream; de_node_baton_t *node = (de_node_baton_t *)file_baton; dump_options_t *opts = node->de_baton->opts; #ifdef USE_TIMING stopwatch_t watch = stopwatch_create(); #endif char *filename; DEBUG_MSG("de_apply_textdelta(%s)\n", node->path); /* Create a new temporary file to write to */ node->filename = apr_psprintf(node->pool, "%s/XXXXXX", opts->temp_dir); apr_file_mktemp(&dest_file, node->filename, APR_CREATE | APR_READ | APR_WRITE | APR_EXCL, pool); dest_stream = svn_stream_from_aprfile2(dest_file, FALSE, pool); /* Update the local copy */ filename = rhash_get(delta_hash, node->path, APR_HASH_KEY_STRING); if (filename == NULL) { src_stream = svn_stream_empty(pool); } else { apr_file_open(&src_file, filename, APR_READ, 0600, pool); src_stream = svn_stream_from_aprfile2(src_file, FALSE, pool); } svn_txdelta_apply(src_stream, dest_stream, node->md5sum, node->path, pool, handler, handler_baton); node->old_filename = apr_pstrdup(node->pool, filename); rhash_set(delta_hash, node->path, APR_HASH_KEY_STRING, node->filename, RHASH_VAL_STRING); DEBUG_MSG("applied delta: %s -> %s\n", node->old_filename, node->filename); node->applied_delta = 1; node->dump_needed = 1; #ifdef USE_TIMING tm_de_apply_textdelta += stopwatch_elapsed(&watch); #endif return SVN_NO_ERROR; }
svn_error_t * svn_fs_x__wrap_temp_rev_file(svn_fs_x__revision_file_t **file, svn_fs_t *fs, apr_file_t *temp_file, apr_pool_t *result_pool) { *file = create_revision_file(fs, result_pool); (*file)->file = temp_file; (*file)->stream = svn_stream_from_aprfile2(temp_file, TRUE, result_pool); return SVN_NO_ERROR; }
/* Deltifies a node, i.e. generates a svndiff that can be dumped */ static svn_error_t *delta_deltify_node(de_node_baton_t *node) { svn_txdelta_stream_t *stream; svn_txdelta_window_handler_t handler; void *handler_baton; svn_stream_t *source, *target, *dest; apr_file_t *source_file = NULL, *target_file = NULL, *dest_file = NULL; dump_options_t *opts = node->de_baton->opts; apr_pool_t *pool = svn_pool_create(node->pool); svn_error_t *err; DEBUG_MSG("delta_deltify_node(%s): %s -> %s\n", node->path, node->old_filename, node->filename); /* Open source and target */ apr_file_open(&target_file, node->filename, APR_READ, 0600, pool); target = svn_stream_from_aprfile2(target_file, FALSE, pool); if (node->old_filename) { apr_file_open(&source_file, node->old_filename, APR_READ, 0600, pool); source = svn_stream_from_aprfile2(source_file, FALSE, pool); } else { source = svn_stream_empty(pool); } /* Open temporary output file */ node->delta_filename = apr_psprintf(node->pool, "%s/XXXXXX", opts->temp_dir); apr_file_mktemp(&dest_file, node->delta_filename, APR_CREATE | APR_READ | APR_WRITE | APR_EXCL, pool); dest = svn_stream_from_aprfile2(dest_file, FALSE, pool); DEBUG_MSG("delta_deltify_node(%s): writing to %s\n", node->path, node->delta_filename); /* Produce delta in svndiff format */ svn_txdelta(&stream, source, target, pool); svn_txdelta_to_svndiff2(&handler, &handler_baton, dest, 0, pool); err = svn_txdelta_send_txstream(stream, handler, handler_baton, pool); svn_pool_destroy(pool); return err; }
/* Copies the data from ORIGINAL_STREAM to a temporary file, returning both the original and compressed size. */ static svn_error_t * create_compressed(apr_file_t **result, svn_filesize_t *full_size, svn_filesize_t *compressed_size, svn_stream_t *original_stream, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stream_t *compressed; svn_filesize_t bytes_read = 0; apr_size_t rd; SVN_ERR(svn_io_open_uniquely_named(result, NULL, NULL, "diffgz", NULL, svn_io_file_del_on_pool_cleanup, result_pool, scratch_pool)); compressed = svn_stream_compressed( svn_stream_from_aprfile2(*result, TRUE, scratch_pool), scratch_pool); if (original_stream) do { char buffer[SVN__STREAM_CHUNK_SIZE]; rd = sizeof(buffer); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_stream_read_full(original_stream, buffer, &rd)); bytes_read += rd; SVN_ERR(svn_stream_write(compressed, buffer, &rd)); } while(rd == SVN__STREAM_CHUNK_SIZE); else { apr_size_t zero = 0; SVN_ERR(svn_stream_write(compressed, NULL, &zero)); } SVN_ERR(svn_stream_close(compressed)); /* Flush compression */ *full_size = bytes_read; SVN_ERR(svn_io_file_size_get(compressed_size, *result, scratch_pool)); return SVN_NO_ERROR; }
svn_error_t * svn_stream_open_readonly(svn_stream_t **stream, const char *path, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_file_t *file; SVN_ERR(svn_io_file_open(&file, path, APR_READ | APR_BUFFERED | APR_BINARY, APR_OS_DEFAULT, result_pool)); *stream = svn_stream_from_aprfile2(file, FALSE, result_pool); return SVN_NO_ERROR; }
svn_error_t * svn_stream_for_stderr(svn_stream_t **err, apr_pool_t *pool) { apr_file_t *stderr_file; apr_status_t apr_err; apr_err = apr_file_open_stderr(&stderr_file, pool); if (apr_err) return svn_error_wrap_apr(apr_err, "Can't open stderr"); *err = svn_stream_from_aprfile2(stderr_file, TRUE, pool); return SVN_NO_ERROR; }
/* Set *CONTENTS to a readable stream from which the pristine text * identified by SHA1_CHECKSUM and PRISTINE_ABSPATH can be read from the * pristine store of WCROOT. If SIZE is not null, set *SIZE to the size * in bytes of that text. If that text is not in the pristine store, * return an error. * * Even if the pristine text is removed from the store while it is being * read, the stream will remain valid and readable until it is closed. * * Allocate the stream in RESULT_POOL. * * This function expects to be executed inside a SQLite txn. * * Implements 'notes/wc-ng/pristine-store' section A-3(d). */ static svn_error_t * pristine_read_txn(svn_stream_t **contents, svn_filesize_t *size, svn_wc__db_wcroot_t *wcroot, const svn_checksum_t *sha1_checksum, const char *pristine_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; /* Check that this pristine text is present in the store. (The presence * of the file is not sufficient.) */ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_PRISTINE_SIZE)); SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (size) *size = svn_sqlite__column_int64(stmt, 0); SVN_ERR(svn_sqlite__reset(stmt)); if (! have_row) { return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL, _("Pristine text '%s' not present"), svn_checksum_to_cstring_display( sha1_checksum, scratch_pool)); } /* Open the file as a readable stream. It will remain readable even when * deleted from disk; APR guarantees that on Windows as well as Unix. * * We also don't enable APR_BUFFERED on this file to maximize throughput * e.g. for fulltext comparison. As we use SVN__STREAM_CHUNK_SIZE buffers * where needed in streams, there is no point in having another layer of * buffers. */ if (contents) { apr_file_t *file; SVN_ERR(svn_io_file_open(&file, pristine_abspath, APR_READ, APR_OS_DEFAULT, result_pool)); *contents = svn_stream_from_aprfile2(file, FALSE, result_pool); } return SVN_NO_ERROR; }
svn_error_t * svn_stream_open_unique(svn_stream_t **stream, const char **temp_path, const char *dirpath, svn_io_file_del_t delete_when, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_file_t *file; SVN_ERR(svn_io_open_unique_file3(&file, temp_path, dirpath, delete_when, result_pool, scratch_pool)); *stream = svn_stream_from_aprfile2(file, FALSE, result_pool); return SVN_NO_ERROR; }
svn_error_t * svn_delta__get_debug_editor(const svn_delta_editor_t **editor, void **edit_baton, const svn_delta_editor_t *wrapped_editor, void *wrapped_edit_baton, apr_pool_t *pool) { svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool); struct edit_baton *eb = apr_palloc(pool, sizeof(*eb)); apr_file_t *errfp; svn_stream_t *out; apr_status_t apr_err = apr_file_open_stderr(&errfp, pool); if (apr_err) return svn_error_wrap_apr(apr_err, "Problem opening stderr"); out = svn_stream_from_aprfile2(errfp, TRUE, pool); tree_editor->set_target_revision = set_target_revision; tree_editor->open_root = open_root; tree_editor->delete_entry = delete_entry; tree_editor->add_directory = add_directory; tree_editor->open_directory = open_directory; tree_editor->change_dir_prop = change_dir_prop; tree_editor->close_directory = close_directory; tree_editor->absent_directory = absent_directory; tree_editor->add_file = add_file; tree_editor->open_file = open_file; tree_editor->apply_textdelta = apply_textdelta; tree_editor->change_file_prop = change_file_prop; tree_editor->close_file = close_file; tree_editor->absent_file = absent_file; tree_editor->close_edit = close_edit; eb->wrapped_editor = wrapped_editor; eb->wrapped_edit_baton = wrapped_edit_baton; eb->out = out; eb->indent_level = 0; *editor = tree_editor; *edit_baton = eb; return SVN_NO_ERROR; }
/* Read a dumpstream from stdin, and use it to feed a loader capable * of transmitting that information to the repository located at URL * (to which SESSION has been opened). AUX_SESSION is a second RA * session opened to the same URL for performing auxiliary out-of-band * operations. */ static svn_error_t * load_revisions(svn_ra_session_t *session, svn_ra_session_t *aux_session, const char *url, svn_boolean_t quiet, apr_pool_t *pool) { apr_file_t *stdin_file; svn_stream_t *stdin_stream; apr_file_open_stdin(&stdin_file, pool); stdin_stream = svn_stream_from_aprfile2(stdin_file, FALSE, pool); SVN_ERR(svn_rdump__load_dumpstream(stdin_stream, session, aux_session, quiet, check_cancel, NULL, pool)); SVN_ERR(svn_stream_close(stdin_stream)); return SVN_NO_ERROR; }
svn_error_t * logger__create(logger_t **logger, const char *filename, apr_pool_t *pool) { logger_t *result = apr_pcalloc(pool, sizeof(*result)); apr_file_t *file; SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_CREATE | APR_APPEND, APR_OS_DEFAULT, pool)); SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool)); result->stream = svn_stream_from_aprfile2(file, FALSE, pool); result->pool = svn_pool_create(pool); *logger = result; return SVN_NO_ERROR; }
svn_error_t * svn_config_write_auth_data(apr_hash_t *hash, const char *cred_kind, const char *realmstring, const char *config_dir, apr_pool_t *pool) { apr_file_t *authfile = NULL; svn_stream_t *stream; const char *auth_path; SVN_ERR(svn_auth__file_path(&auth_path, cred_kind, realmstring, config_dir, pool)); if (! auth_path) return svn_error_create(SVN_ERR_NO_AUTH_FILE_PATH, NULL, _("Unable to locate auth file")); /* Add the realmstring to the hash, so programs (or users) can verify exactly which set of credentials this file holds. */ svn_hash_sets(hash, SVN_CONFIG_REALMSTRING_KEY, svn_string_create(realmstring, pool)); SVN_ERR_W(svn_io_file_open(&authfile, auth_path, (APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED), APR_OS_DEFAULT, pool), _("Unable to open auth file for writing")); stream = svn_stream_from_aprfile2(authfile, FALSE, pool); SVN_ERR_W(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, pool), apr_psprintf(pool, _("Error writing hash to '%s'"), svn_dirent_local_style(auth_path, pool))); SVN_ERR(svn_stream_close(stream)); /* To be nice, remove the realmstring from the hash again, just in case the caller wants their hash unchanged. */ svn_hash_sets(hash, SVN_CONFIG_REALMSTRING_KEY, NULL); return SVN_NO_ERROR; }
bool CAppUtils::CreateUnifiedDiff(const CString& orig, const CString& modified, const CString& output, bool bShowError) { apr_file_t * outfile = NULL; apr_pool_t * pool = svn_pool_create(NULL); svn_error_t * err = svn_io_file_open (&outfile, svn_path_internal_style(CUnicodeUtils::GetUTF8(output), pool), APR_WRITE | APR_CREATE | APR_BINARY | APR_TRUNCATE, APR_OS_DEFAULT, pool); if (err == NULL) { svn_stream_t * stream = svn_stream_from_aprfile2(outfile, false, pool); if (stream) { svn_diff_t * diff = NULL; svn_diff_file_options_t * opts = svn_diff_file_options_create(pool); opts->ignore_eol_style = false; opts->ignore_space = svn_diff_file_ignore_space_none; err = svn_diff_file_diff_2(&diff, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig), pool), svn_path_internal_style(CUnicodeUtils::GetUTF8(modified), pool), opts, pool); if (err == NULL) { err = svn_diff_file_output_unified(stream, diff, svn_path_internal_style(CUnicodeUtils::GetUTF8(orig), pool), svn_path_internal_style(CUnicodeUtils::GetUTF8(modified), pool), NULL, NULL, pool); svn_stream_close(stream); } } apr_file_close(outfile); } if (err) { if (bShowError) AfxMessageBox(CAppUtils::GetErrorString(err), MB_ICONERROR); svn_error_clear(err); svn_pool_destroy(pool); return false; } svn_pool_destroy(pool); return true; }
/*** Public interfaces. ***/ svn_error_t * svn_ra__get_debug_reporter(const svn_ra_reporter3_t **reporter, void **report_baton, const svn_ra_reporter3_t *wrapped_reporter, void *wrapped_report_baton, apr_pool_t *pool) { svn_ra_reporter3_t *tree_reporter; struct report_baton *rb; apr_file_t *errfp; svn_stream_t *out; apr_status_t apr_err = apr_file_open_stderr(&errfp, pool); if (apr_err) return svn_error_wrap_apr(apr_err, "Problem opening stderr"); out = svn_stream_from_aprfile2(errfp, TRUE, pool); /* ### svn_delta_default_editor() */ tree_reporter = apr_palloc(pool, sizeof(*tree_reporter)); rb = apr_palloc(pool, sizeof(*rb)); tree_reporter->set_path = set_path; tree_reporter->delete_path = delete_path; tree_reporter->link_path = link_path; tree_reporter->finish_report = finish_report; tree_reporter->abort_report = abort_report; rb->wrapped_reporter = wrapped_reporter; rb->wrapped_report_baton = wrapped_report_baton; rb->out = out; *reporter = tree_reporter; *report_baton = rb; return SVN_NO_ERROR; }
svn_error_t * svn_ra__file_revs_from_log(svn_ra_session_t *ra_session, const char *path, svn_revnum_t start, svn_revnum_t end, svn_file_rev_handler_t handler, void *handler_baton, apr_pool_t *pool) { svn_node_kind_t kind; const char *repos_url, *session_url, *fs_path; apr_array_header_t *condensed_targets; struct fr_log_message_baton lmb; struct rev *rev; apr_hash_t *last_props; svn_stream_t *last_stream; apr_pool_t *currpool, *lastpool; /* Fetch the absolute FS path associated with PATH. */ SVN_ERR(get_fs_path(&fs_path, ra_session, path, pool)); /* Check to make sure we're dealing with a file. */ SVN_ERR(svn_ra_check_path(ra_session, path, end, &kind, pool)); if (kind == svn_node_dir) return svn_error_createf(SVN_ERR_FS_NOT_FILE, NULL, _("'%s' is not a file"), fs_path); condensed_targets = apr_array_make(pool, 1, sizeof(const char *)); APR_ARRAY_PUSH(condensed_targets, const char *) = path; lmb.path = fs_path; lmb.eldest = NULL; lmb.pool = pool; /* Accumulate revision metadata by walking the revisions backwards; this allows us to follow moves/copies correctly. */ SVN_ERR(svn_ra_get_log2(ra_session, condensed_targets, end, start, 0, /* no limit */ TRUE, FALSE, FALSE, NULL, fr_log_message_receiver, &lmb, pool)); /* Reparent the session while we go back through the history. */ SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, pool)); SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, pool)); SVN_ERR(svn_ra_reparent(ra_session, repos_url, pool)); currpool = svn_pool_create(pool); lastpool = svn_pool_create(pool); /* We want the first txdelta to be against the empty file. */ last_props = apr_hash_make(lastpool); last_stream = svn_stream_empty(lastpool); /* Walk the revision list in chronological order, downloading each fulltext, diffing it with its predecessor, and calling the file_revs handler for each one. Use two iteration pools rather than one, because the diff routines need to look at a sliding window of revisions. Two pools gives us a ring buffer of sorts. */ for (rev = lmb.eldest; rev; rev = rev->next) { const char *temp_path; apr_pool_t *tmppool; apr_hash_t *props; apr_file_t *file; svn_stream_t *stream; apr_array_header_t *prop_diffs; svn_txdelta_stream_t *delta_stream; svn_txdelta_window_handler_t delta_handler = NULL; void *delta_baton = NULL; svn_pool_clear(currpool); /* Get the contents of the file from the repository, and put them in a temporary local file. */ SVN_ERR(svn_stream_open_unique(&stream, &temp_path, NULL, svn_io_file_del_on_pool_cleanup, currpool, currpool)); SVN_ERR(svn_ra_get_file(ra_session, rev->path + 1, rev->revision, stream, NULL, &props, currpool)); SVN_ERR(svn_stream_close(stream)); /* Open up a stream to the local file. */ SVN_ERR(svn_io_file_open(&file, temp_path, APR_READ, APR_OS_DEFAULT, currpool)); stream = svn_stream_from_aprfile2(file, FALSE, currpool); /* Calculate the property diff */ SVN_ERR(svn_prop_diffs(&prop_diffs, props, last_props, lastpool)); /* Call the file_rev handler */ SVN_ERR(handler(handler_baton, rev->path, rev->revision, rev->props, FALSE, /* merged revision */ &delta_handler, &delta_baton, prop_diffs, lastpool)); /* Compute and send delta if client asked for it. */ if (delta_handler) { /* Get the content delta. Don't calculate checksums as we don't * use them. */ svn_txdelta2(&delta_stream, last_stream, stream, FALSE, lastpool); /* And send. */ SVN_ERR(svn_txdelta_send_txstream(delta_stream, delta_handler, delta_baton, lastpool)); } /* Switch the pools and data for the next iteration */ tmppool = currpool; currpool = lastpool; lastpool = tmppool; SVN_ERR(svn_stream_close(last_stream)); last_stream = stream; last_props = props; } SVN_ERR(svn_stream_close(last_stream)); svn_pool_destroy(currpool); svn_pool_destroy(lastpool); /* Reparent the session back to the original URL. */ return svn_ra_reparent(ra_session, session_url, pool); }
/* Core implementation of svn_fs_fs__open_pack_or_rev_file working on an * existing, initialized FILE structure. If WRITABLE is TRUE, give write * access to the file - temporarily resetting the r/o state if necessary. */ static svn_error_t * open_pack_or_rev_file(svn_fs_x__revision_file_t *file, svn_fs_t *fs, svn_revnum_t rev, svn_boolean_t writable, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_error_t *err; svn_boolean_t retry = FALSE; do { const char *path = svn_fs_x__path_rev_absolute(fs, rev, scratch_pool); apr_file_t *apr_file; apr_int32_t flags = writable ? APR_READ | APR_WRITE | APR_BUFFERED : APR_READ | APR_BUFFERED; /* We may have to *temporarily* enable write access. */ err = writable ? auto_make_writable(path, result_pool, scratch_pool) : SVN_NO_ERROR; /* open the revision file in buffered r/o or r/w mode */ if (!err) err = svn_io_file_open(&apr_file, path, flags, APR_OS_DEFAULT, result_pool); if (!err) { file->file = apr_file; file->stream = svn_stream_from_aprfile2(apr_file, TRUE, result_pool); return SVN_NO_ERROR; } if (err && APR_STATUS_IS_ENOENT(err->apr_err)) { /* Could not open the file. This may happen if the * file once existed but got packed later. */ svn_error_clear(err); /* if that was our 2nd attempt, leave it at that. */ if (retry) return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, _("No such revision %ld"), rev); /* We failed for the first time. Refresh cache & retry. */ SVN_ERR(svn_fs_x__update_min_unpacked_rev(fs, scratch_pool)); file->start_revision = svn_fs_x__packed_base_rev(fs, rev); retry = TRUE; } else { retry = FALSE; } } while (retry); return svn_error_trace(err); }
svn_error_t * svn_hash_write(apr_hash_t *hash, apr_file_t *destfile, apr_pool_t *pool) { return hash_write(hash, NULL, svn_stream_from_aprfile2(destfile, TRUE, pool), SVN_HASH_TERMINATOR, pool); }
static svn_error_t * open_tunnel(svn_stream_t **request, svn_stream_t **response, svn_ra_close_tunnel_func_t *close_func, void **close_baton, void *tunnel_baton, const char *tunnel_name, const char *user, const char *hostname, int port, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { svn_node_kind_t kind; apr_proc_t *proc; apr_procattr_t *attr; apr_status_t status; const char *args[] = { "svnserve", "-t", "-r", ".", NULL }; const char *svnserve; tunnel_baton_t *b = tunnel_baton; close_baton_t *cb; SVN_TEST_ASSERT(b->magic == TUNNEL_MAGIC); SVN_ERR(svn_dirent_get_absolute(&svnserve, "../../svnserve/svnserve", pool)); #ifdef WIN32 svnserve = apr_pstrcat(pool, svnserve, ".exe", SVN_VA_NULL); #endif SVN_ERR(svn_io_check_path(svnserve, &kind, pool)); if (kind != svn_node_file) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Could not find svnserve at %s", svn_dirent_local_style(svnserve, pool)); status = apr_procattr_create(&attr, pool); if (status == APR_SUCCESS) status = apr_procattr_io_set(attr, 1, 1, 0); if (status == APR_SUCCESS) status = apr_procattr_cmdtype_set(attr, APR_PROGRAM); proc = apr_palloc(pool, sizeof(*proc)); if (status == APR_SUCCESS) status = apr_proc_create(proc, svn_dirent_local_style(svnserve, pool), args, NULL, attr, pool); if (status != APR_SUCCESS) return svn_error_wrap_apr(status, "Could not run svnserve"); apr_pool_note_subprocess(pool, proc, APR_KILL_NEVER); /* APR pipe objects inherit by default. But we don't want the * tunnel agent's pipes held open by future child processes * (such as other ra_svn sessions), so turn that off. */ apr_file_inherit_unset(proc->in); apr_file_inherit_unset(proc->out); cb = apr_pcalloc(pool, sizeof(*cb)); cb->magic = CLOSE_MAGIC; cb->tb = b; cb->proc = proc; *request = svn_stream_from_aprfile2(proc->in, FALSE, pool); *response = svn_stream_from_aprfile2(proc->out, FALSE, pool); *close_func = close_tunnel; *close_baton = cb; ++b->open_count; return SVN_NO_ERROR; }
static svn_error_t * test_stream_seek_file(apr_pool_t *pool) { static const char *file_data[2] = {"One", "Two"}; svn_stream_t *stream; svn_stringbuf_t *line; svn_boolean_t eof; apr_file_t *f; static const char *fname = "test_stream_seek.txt"; int j; apr_status_t status; static const char *NL = APR_EOL_STR; svn_stream_mark_t *mark; status = apr_file_open(&f, fname, (APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_DELONCLOSE), APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot open '%s'", fname); /* Create the file. */ for (j = 0; j < 2; j++) { apr_size_t len; len = strlen(file_data[j]); status = apr_file_write(f, file_data[j], &len); if (status || len != strlen(file_data[j])) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot write to '%s'", fname); len = strlen(NL); status = apr_file_write(f, NL, &len); if (status || len != strlen(NL)) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot write to '%s'", fname); } /* Create a stream to read from the file. */ stream = svn_stream_from_aprfile2(f, FALSE, pool); SVN_ERR(svn_stream_reset(stream)); SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[0]) == 0); /* Set a mark at the beginning of the second line of the file. */ SVN_ERR(svn_stream_mark(stream, &mark, pool)); /* Read the second line and then seek back to the mark. */ SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[1]) == 0); SVN_ERR(svn_stream_seek(stream, mark)); /* The next read should return the second line again. */ SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[1]) == 0); /* The next read should return EOF. */ SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(eof); /* Go back to the beginning of the last line and try to skip it * NOT including the EOL. */ SVN_ERR(svn_stream_seek(stream, mark)); SVN_ERR(svn_stream_skip(stream, strlen(file_data[1]))); /* The remaining line should be empty */ SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(! eof && strcmp(line->data, "") == 0); /* The next read should return EOF. */ SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool)); SVN_TEST_ASSERT(eof); SVN_ERR(svn_stream_close(stream)); return SVN_NO_ERROR; }
/* This helper is the main "meat" of the editor -- it does all the work of writing a node record. Write out a node record for PATH of type KIND under EB->FS_ROOT. ACTION describes what is happening to the node (see enum svn_node_action). Write record to writable EB->STREAM, using EB->BUFFER to write in chunks. If the node was itself copied, IS_COPY is TRUE and the path/revision of the copy source are in CMP_PATH/CMP_REV. If IS_COPY is FALSE, yet CMP_PATH/CMP_REV are valid, this node is part of a copied subtree. */ static svn_error_t * dump_node(struct edit_baton *eb, const char *path, svn_node_kind_t kind, enum svn_node_action action, svn_boolean_t is_copy, const char *cmp_path, svn_revnum_t cmp_rev, apr_pool_t *pool) { svn_stringbuf_t *propstring; svn_filesize_t content_length = 0; apr_size_t len; svn_boolean_t must_dump_text = FALSE, must_dump_props = FALSE; const char *compare_path = path; svn_revnum_t compare_rev = eb->current_rev - 1; svn_fs_root_t *compare_root = NULL; apr_file_t *delta_file = NULL; /* Maybe validate the path. */ if (eb->verify || eb->notify_func) { svn_error_t *err = svn_fs__path_valid(path, pool); if (err) { if (eb->notify_func) { char errbuf[512]; /* ### svn_strerror() magic number */ svn_repos_notify_t *notify; notify = svn_repos_notify_create(svn_repos_notify_warning, pool); notify->warning = svn_repos_notify_warning_invalid_fspath; notify->warning_str = apr_psprintf( pool, _("E%06d: While validating fspath '%s': %s"), err->apr_err, path, svn_err_best_message(err, errbuf, sizeof(errbuf))); eb->notify_func(eb->notify_baton, notify, pool); } /* Return the error in addition to notifying about it. */ if (eb->verify) return svn_error_trace(err); else svn_error_clear(err); } } /* Write out metadata headers for this file node. */ SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_PATH ": %s\n", path)); if (kind == svn_node_file) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_KIND ": file\n")); else if (kind == svn_node_dir) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_KIND ": dir\n")); /* Remove leading slashes from copyfrom paths. */ if (cmp_path) cmp_path = svn_relpath_canonicalize(cmp_path, pool); /* Validate the comparison path/rev. */ if (ARE_VALID_COPY_ARGS(cmp_path, cmp_rev)) { compare_path = cmp_path; compare_rev = cmp_rev; } if (action == svn_node_action_change) { SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": change\n")); /* either the text or props changed, or possibly both. */ SVN_ERR(svn_fs_revision_root(&compare_root, svn_fs_root_fs(eb->fs_root), compare_rev, pool)); SVN_ERR(svn_fs_props_changed(&must_dump_props, compare_root, compare_path, eb->fs_root, path, pool)); if (kind == svn_node_file) SVN_ERR(svn_fs_contents_changed(&must_dump_text, compare_root, compare_path, eb->fs_root, path, pool)); } else if (action == svn_node_action_replace) { if (! is_copy) { /* a simple delete+add, implied by a single 'replace' action. */ SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": replace\n")); /* definitely need to dump all content for a replace. */ if (kind == svn_node_file) must_dump_text = TRUE; must_dump_props = TRUE; } else { /* more complex: delete original, then add-with-history. */ /* the path & kind headers have already been printed; just add a delete action, and end the current record.*/ SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n\n")); /* recurse: print an additional add-with-history record. */ SVN_ERR(dump_node(eb, path, kind, svn_node_action_add, is_copy, compare_path, compare_rev, pool)); /* we can leave this routine quietly now, don't need to dump any content; that was already done in the second record. */ must_dump_text = FALSE; must_dump_props = FALSE; } } else if (action == svn_node_action_delete) { SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": delete\n")); /* we can leave this routine quietly now, don't need to dump any content. */ must_dump_text = FALSE; must_dump_props = FALSE; } else if (action == svn_node_action_add) { SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_ACTION ": add\n")); if (! is_copy) { /* Dump all contents for a simple 'add'. */ if (kind == svn_node_file) must_dump_text = TRUE; must_dump_props = TRUE; } else { if (!eb->verify && cmp_rev < eb->oldest_dumped_rev && eb->notify_func) { svn_repos_notify_t *notify = svn_repos_notify_create(svn_repos_notify_warning, pool); notify->warning = svn_repos_notify_warning_found_old_reference; notify->warning_str = apr_psprintf( pool, _("Referencing data in revision %ld," " which is older than the oldest" " dumped revision (r%ld). Loading this dump" " into an empty repository" " will fail."), cmp_rev, eb->oldest_dumped_rev); eb->found_old_reference = TRUE; eb->notify_func(eb->notify_baton, notify, pool); } SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV ": %ld\n" SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH ": %s\n", cmp_rev, cmp_path)); SVN_ERR(svn_fs_revision_root(&compare_root, svn_fs_root_fs(eb->fs_root), compare_rev, pool)); /* Need to decide if the copied node had any extra textual or property mods as well. */ SVN_ERR(svn_fs_props_changed(&must_dump_props, compare_root, compare_path, eb->fs_root, path, pool)); if (kind == svn_node_file) { svn_checksum_t *checksum; const char *hex_digest; SVN_ERR(svn_fs_contents_changed(&must_dump_text, compare_root, compare_path, eb->fs_root, path, pool)); SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, compare_root, compare_path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_MD5 ": %s\n", hex_digest)); SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, compare_root, compare_path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_COPY_SOURCE_SHA1 ": %s\n", hex_digest)); } } } if ((! must_dump_text) && (! must_dump_props)) { /* If we're not supposed to dump text or props, so be it, we can just go home. However, if either one needs to be dumped, then our dumpstream format demands that at a *minimum*, we see a lone "PROPS-END" as a divider between text and props content within the content-block. */ len = 2; return svn_stream_write(eb->stream, "\n\n", &len); /* ### needed? */ } /*** Start prepping content to dump... ***/ /* If we are supposed to dump properties, write out a property length header and generate a stringbuf that contains those property values here. */ if (must_dump_props) { apr_hash_t *prophash, *oldhash = NULL; apr_size_t proplen; svn_stream_t *propstream; SVN_ERR(svn_fs_node_proplist(&prophash, eb->fs_root, path, pool)); /* If this is a partial dump, then issue a warning if we dump mergeinfo properties that refer to revisions older than the first revision dumped. */ if (!eb->verify && eb->notify_func && eb->oldest_dumped_rev > 1) { svn_string_t *mergeinfo_str = apr_hash_get(prophash, SVN_PROP_MERGEINFO, APR_HASH_KEY_STRING); if (mergeinfo_str) { svn_mergeinfo_t mergeinfo, old_mergeinfo; SVN_ERR(svn_mergeinfo_parse(&mergeinfo, mergeinfo_str->data, pool)); SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges( &old_mergeinfo, mergeinfo, eb->oldest_dumped_rev - 1, 0, TRUE, pool, pool)); if (apr_hash_count(old_mergeinfo)) { svn_repos_notify_t *notify = svn_repos_notify_create(svn_repos_notify_warning, pool); notify->warning = svn_repos_notify_warning_found_old_mergeinfo; notify->warning_str = apr_psprintf( pool, _("Mergeinfo referencing revision(s) prior " "to the oldest dumped revision (r%ld). " "Loading this dump may result in invalid " "mergeinfo."), eb->oldest_dumped_rev); eb->found_old_mergeinfo = TRUE; eb->notify_func(eb->notify_baton, notify, pool); } } } if (eb->use_deltas && compare_root) { /* Fetch the old property hash to diff against and output a header saying that our property contents are a delta. */ SVN_ERR(svn_fs_node_proplist(&oldhash, compare_root, compare_path, pool)); SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_PROP_DELTA ": true\n")); } else oldhash = apr_hash_make(pool); propstring = svn_stringbuf_create_ensure(0, pool); propstream = svn_stream_from_stringbuf(propstring, pool); SVN_ERR(svn_hash_write_incremental(prophash, oldhash, propstream, "PROPS-END", pool)); SVN_ERR(svn_stream_close(propstream)); proplen = propstring->len; content_length += proplen; SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH ": %" APR_SIZE_T_FMT "\n", proplen)); } /* If we are supposed to dump text, write out a text length header here, and an MD5 checksum (if available). */ if (must_dump_text && (kind == svn_node_file)) { svn_checksum_t *checksum; const char *hex_digest; svn_filesize_t textlen; if (eb->use_deltas) { /* Compute the text delta now and write it into a temporary file, so that we can find its length. Output a header saying our text contents are a delta. */ SVN_ERR(store_delta(&delta_file, &textlen, compare_root, compare_path, eb->fs_root, path, pool)); SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_DELTA ": true\n")); if (compare_root) { SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, compare_root, compare_path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5 ": %s\n", hex_digest)); SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, compare_root, compare_path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_SHA1 ": %s\n", hex_digest)); } } else { /* Just fetch the length of the file. */ SVN_ERR(svn_fs_file_length(&textlen, eb->fs_root, path, pool)); } content_length += textlen; SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_CONTENT_LENGTH ": %" SVN_FILESIZE_T_FMT "\n", textlen)); SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, eb->fs_root, path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5 ": %s\n", hex_digest)); SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, eb->fs_root, path, FALSE, pool)); hex_digest = svn_checksum_to_cstring(checksum, pool); if (hex_digest) SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_TEXT_CONTENT_SHA1 ": %s\n", hex_digest)); } /* 'Content-length:' is the last header before we dump the content, and is the sum of the text and prop contents lengths. We write this only for the benefit of non-Subversion RFC-822 parsers. */ SVN_ERR(svn_stream_printf(eb->stream, pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH ": %" SVN_FILESIZE_T_FMT "\n\n", content_length)); /* Dump property content if we're supposed to do so. */ if (must_dump_props) { len = propstring->len; SVN_ERR(svn_stream_write(eb->stream, propstring->data, &len)); } /* Dump text content */ if (must_dump_text && (kind == svn_node_file)) { svn_stream_t *contents; if (delta_file) { /* Make sure to close the underlying file when the stream is closed. */ contents = svn_stream_from_aprfile2(delta_file, FALSE, pool); } else SVN_ERR(svn_fs_file_contents(&contents, eb->fs_root, path, pool)); SVN_ERR(svn_stream_copy3(contents, svn_stream_disown(eb->stream, pool), NULL, NULL, pool)); } len = 2; return svn_stream_write(eb->stream, "\n\n", &len); /* ### needed? */ }
static guint svn_cat_command_run (AnjutaCommand *command) { SvnCatCommand *self; SvnCommand *svn_command; svn_opt_revision_t revision; svn_opt_revision_t peg_revision; svn_stream_t *cat_stream; apr_file_t *cat_input; apr_file_t *cat_output; apr_size_t read_size; gchar *line; svn_error_t *error; apr_status_t apr_error; self = SVN_CAT_COMMAND (command); svn_command = SVN_COMMAND (command); apr_file_pipe_create (&cat_output, &cat_input, svn_command_get_pool (svn_command)); apr_file_pipe_timeout_set (cat_output, 0); apr_file_pipe_timeout_set (cat_input, 0); cat_stream = svn_stream_from_aprfile2 (cat_input, FALSE, svn_command_get_pool (svn_command)); revision.kind = svn_opt_revision_number; revision.value.number = self->priv->revision; peg_revision.kind = svn_opt_revision_unspecified; error = svn_client_cat2 (cat_stream, self->priv->path, &peg_revision, &revision, svn_command_get_client_context (svn_command), svn_command_get_pool (svn_command)); if (error) { svn_command_set_error (svn_command, error); return 1; } while (apr_file_eof (cat_output) != APR_EOF) { read_size = 80; line = g_new0 (gchar, (read_size + 1)); apr_error = apr_file_read (cat_output, line, &read_size); if (apr_error) break; if (strlen (line)) { anjuta_async_command_lock (ANJUTA_ASYNC_COMMAND (command)); g_queue_push_tail (self->priv->output, g_strdup (line)); anjuta_async_command_unlock (ANJUTA_ASYNC_COMMAND (command)); g_free (line); anjuta_command_notify_data_arrived (command); } } return 0; }
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; }