Esempio n. 1
0
static svn_error_t *
test_serialization(apr_pool_t *pool)
{
  svn_stringbuf_t *original_content;
  svn_stringbuf_t *written_content;
  svn_config_t *cfg;

  const struct
    {
      const char *section;
      const char *option;
      const char *value;
    } test_data[] =
    {
      { "my section", "value1", "some" },
      { "my section", "value2", "something" },
      { "another Section", "value1", "one" },
      { "another Section", "value2", "two" },
      { "another Section", "value 3", "more" },
    };
  int i;

  /* Format the original with the same formatting that the writer will use. */
  original_content = svn_stringbuf_create("\n[my section]\n"
                                          "value1=some\n"
                                          "value2=%(value1)sthing\n"
                                          "\n[another Section]\n"
                                          "value1=one\n"
                                          "value2=two\n"
                                          "value 3=more\n",
                                          pool);
  written_content = svn_stringbuf_create_empty(pool);

  SVN_ERR(svn_config_parse(&cfg,
                           svn_stream_from_stringbuf(original_content, pool),
                           TRUE, TRUE, pool));
  SVN_ERR(svn_config__write(svn_stream_from_stringbuf(written_content, pool),
                            cfg, pool));
  SVN_ERR(svn_config_parse(&cfg,
                           svn_stream_from_stringbuf(written_content, pool),
                           TRUE, TRUE, pool));

  /* The serialized and re-parsed config must have the expected contents. */
  for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); ++i)
    {
      const char *val;
      svn_config_get(cfg, &val, test_data[i].section, test_data[i].option,
                     NULL);
      SVN_TEST_STRING_ASSERT(val, test_data[i].value);
    }

  return SVN_NO_ERROR;
}
Esempio n. 2
0
/*
 * mw_svn_get()
 *
 * Return the contents of the head of the file at subversion location
 * <url>.  On failure return NULL.
 */
char *
mw_svn_get(const char *url, void *baton, apr_pool_t *pool)
{
	svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
	svn_stream_t *out;
	apr_pool_t *subpool = svn_pool_create(pool);
	svn_stringbuf_t *string;
	svn_error_t *err = NULL;
	svn_opt_revision_t rev;
	char *res;

	string = svn_stringbuf_create("", pool);
	out = svn_stream_from_stringbuf(string, pool);

	/* For now, we always want the HEAD revision, but in future we
	 * may want to support specifying a revision here.*/
	rev.kind = svn_opt_revision_head;

	svn_pool_clear(subpool);

	err = svn_client_cat(out, url, &rev, ctx, subpool);

	if (err != NULL) {
		svn_pool_destroy(subpool);
		svn_stream_close(out);
		return (NULL);
	}

	res = xstrdup(string->data);

	svn_pool_destroy(subpool);
	svn_stream_close(out);

	return (res);
}
Esempio n. 3
0
static svn_error_t *
test_stream_base64(apr_pool_t *pool)
{
  svn_stream_t *stream;
  svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool);
  int i;
  static const char *strings[] = {
    "fairly boring test data... blah blah",
    "A",
    "abc",
    "012345679",
    NULL
  };

  stream = svn_stream_from_stringbuf(actual, pool);
  stream = svn_base64_decode(stream, pool);
  stream = svn_base64_encode(stream, pool);

  for (i = 0; strings[i]; i++)
    {
      apr_size_t len = strlen(strings[i]);

      svn_stringbuf_appendbytes(expected, strings[i], len);
      SVN_ERR(svn_stream_write(stream, strings[i], &len));
    }

  SVN_ERR(svn_stream_close(stream));

  SVN_TEST_STRING_ASSERT(actual->data, expected->data);

  return SVN_NO_ERROR;
}
Esempio n. 4
0
svn_error_t *
svn_fs_fs__dag_serialize(char **data,
                         apr_size_t *data_len,
                         void *in,
                         apr_pool_t *pool)
{
    dag_node_t *node = in;
    svn_stringbuf_t *buf = svn_stringbuf_create("", pool);

    if (svn_fs_fs__dag_check_mutable(node))
    {
        svn_stringbuf_appendcstr(buf, "M");
        svn_stringbuf_appendcstr(buf, (node->kind == svn_node_file ? "F" : "D"));
        svn_stringbuf_appendcstr(buf, svn_fs_fs__id_unparse(node->id,
                                 pool)->data);
        svn_stringbuf_appendcstr(buf, "\n");
        svn_stringbuf_appendcstr(buf, node->created_path);
    }
    else
    {
        fs_fs_data_t *ffd = node->fs->fsap_data;
        svn_stringbuf_appendcstr(buf, "I");
        SVN_ERR(svn_fs_fs__write_noderev(svn_stream_from_stringbuf(buf, pool),
                                         node->node_revision, ffd->format,
                                         TRUE, pool));
    }

    *data = buf->data;
    *data_len = buf->len;
    return SVN_NO_ERROR;
}
Esempio n. 5
0
/* Helper for svn_repos_dump_fs.

   Write a revision record of REV in FS to writable STREAM, using POOL.
 */
static svn_error_t *
write_revision_record(svn_stream_t *stream,
                      svn_fs_t *fs,
                      svn_revnum_t rev,
                      apr_pool_t *pool)
{
  apr_size_t len;
  apr_hash_t *props;
  svn_stringbuf_t *encoded_prophash;
  apr_time_t timetemp;
  svn_string_t *datevalue;
  svn_stream_t *propstream;

  /* Read the revision props even if we're aren't going to dump
     them for verification purposes */
  SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));

  /* Run revision date properties through the time conversion to
     canonicalize them. */
  /* ### Remove this when it is no longer needed for sure. */
  datevalue = apr_hash_get(props, SVN_PROP_REVISION_DATE,
                           APR_HASH_KEY_STRING);
  if (datevalue)
    {
      SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool));
      datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool),
                                    pool);
      apr_hash_set(props, SVN_PROP_REVISION_DATE, APR_HASH_KEY_STRING,
                   datevalue);
    }

  encoded_prophash = svn_stringbuf_create_ensure(0, pool);
  propstream = svn_stream_from_stringbuf(encoded_prophash, pool);
  SVN_ERR(svn_hash_write2(props, propstream, "PROPS-END", pool));
  SVN_ERR(svn_stream_close(propstream));

  /* ### someday write a revision-content-checksum */

  SVN_ERR(svn_stream_printf(stream, pool,
                            SVN_REPOS_DUMPFILE_REVISION_NUMBER
                            ": %ld\n", rev));
  SVN_ERR(svn_stream_printf(stream, pool,
                            SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                            ": %" APR_SIZE_T_FMT "\n",
                            encoded_prophash->len));

  /* Write out a regular Content-length header for the benefit of
     non-Subversion RFC-822 parsers. */
  SVN_ERR(svn_stream_printf(stream, pool,
                            SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                            ": %" APR_SIZE_T_FMT "\n\n",
                            encoded_prophash->len));

  len = encoded_prophash->len;
  SVN_ERR(svn_stream_write(stream, encoded_prophash->data, &len));

  len = 1;
  return svn_stream_write(stream, "\n", &len);
}
Esempio n. 6
0
inline Try<std::string> patch(const std::string& s, const Diff& diff)
{
  // Initialize the Apache Portable Runtime subsystem, as necessary
  // for using the svn library.
  initialize();

  // Note that svn_pool_create wraps apr_pool_create_ex, which is
  // thread safe, see: http://goo.gl/NX0hps.
  apr_pool_t* pool = svn_pool_create(NULL);

  // We want to apply the svndiff format diff to the source trying to
  // produce a result. First setup a handler for applying a text delta
  // to the source stream.
  svn_string_t source;
  source.data = s.data();
  source.len = s.length();

  svn_txdelta_window_handler_t handler;
  void* baton = NULL;

  svn_stringbuf_t* patched = svn_stringbuf_create_ensure(s.length(), pool);

  svn_txdelta_apply(
      svn_stream_from_string(&source, pool),
      svn_stream_from_stringbuf(patched, pool),
      NULL,
      NULL,
      pool,
      &handler,
      &baton);

  // Setup a stream that converts an svndiff format diff to a text
  // delta, so that we can use our handler to patch the source string.
  svn_stream_t* stream = svn_txdelta_parse_svndiff(
      handler,
      baton,
      TRUE,
      pool);

  // Now feed the diff into the stream to compute the patched result.
  const char* data = diff.data.data();
  apr_size_t length = diff.data.length();

  svn_error_t* error = svn_stream_write(stream, data, &length);

  if (error != NULL) {
    char buffer[1024];
    std::string message(svn_err_best_message(error, buffer, 1024));
    svn_pool_destroy(pool);
    return Error(message);
  }

  std::string result(patched->data, patched->len);

  svn_pool_destroy(pool);

  return result;
}
Esempio n. 7
0
static svn_error_t *
store_and_load_table(string_table_t **table, apr_pool_t *pool)
{
    svn_stringbuf_t *stream_buffer = svn_stringbuf_create_empty(pool);
    svn_stream_t *stream;

    stream = svn_stream_from_stringbuf(stream_buffer, pool);
    SVN_ERR(svn_fs_x__write_string_table(stream, *table, pool));
    SVN_ERR(svn_stream_close(stream));

    *table = NULL;

    stream = svn_stream_from_stringbuf(stream_buffer, pool);
    SVN_ERR(svn_fs_x__read_string_table(table, stream, pool, pool));
    SVN_ERR(svn_stream_close(stream));

    return SVN_NO_ERROR;
}
Esempio n. 8
0
static svn_error_t *
test_stringbuf_from_stream(apr_pool_t *pool)
{
  const char *test_cases[] =
    {
      "",
      "x",
      "this string is longer than the default 64 minimum block size used"
      "by the function under test",
      NULL
    };

  const char **test_case;
  for (test_case = test_cases; *test_case; ++test_case)
    {
      svn_stringbuf_t *result1, *result2, *result3, *result4;
      svn_stringbuf_t *original = svn_stringbuf_create(*test_case, pool);

      svn_stream_t *stream1 = svn_stream_from_stringbuf(original, pool);
      svn_stream_t *stream2 = svn_stream_from_stringbuf(original, pool);

      SVN_ERR(svn_stringbuf_from_stream(&result1, stream1, 0, pool));
      SVN_ERR(svn_stringbuf_from_stream(&result2, stream1, 0, pool));
      SVN_ERR(svn_stringbuf_from_stream(&result3, stream2, original->len,
                                        pool));
      SVN_ERR(svn_stringbuf_from_stream(&result4, stream2, original->len,
                                        pool));

      /* C-string contents must match */
      SVN_TEST_STRING_ASSERT(result1->data, original->data);
      SVN_TEST_STRING_ASSERT(result2->data, "");
      SVN_TEST_STRING_ASSERT(result3->data, original->data);
      SVN_TEST_STRING_ASSERT(result4->data, "");

      /* assumed length must match */
      SVN_TEST_ASSERT(result1->len == original->len);
      SVN_TEST_ASSERT(result2->len == 0);
      SVN_TEST_ASSERT(result3->len == original->len);
      SVN_TEST_ASSERT(result4->len == 0);
    }

  return SVN_NO_ERROR;
}
Esempio n. 9
0
static svn_error_t *
test_stream_tee(apr_pool_t *pool)
{
  svn_stringbuf_t *test_bytes = generate_test_bytes(100, pool);
  svn_stringbuf_t *output_buf1 = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *output_buf2 = svn_stringbuf_create_empty(pool);
  svn_stream_t *source_stream = svn_stream_from_stringbuf(test_bytes, pool);
  svn_stream_t *output_stream1 = svn_stream_from_stringbuf(output_buf1, pool);
  svn_stream_t *output_stream2 = svn_stream_from_stringbuf(output_buf2, pool);
  svn_stream_t *tee_stream;

  tee_stream = svn_stream_tee(output_stream1, output_stream2, pool);
  SVN_ERR(svn_stream_copy3(source_stream, tee_stream, NULL, NULL, pool));

  if (!svn_stringbuf_compare(output_buf1, output_buf2))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "Duplicated streams did not match.");

  return SVN_NO_ERROR;
}
Esempio n. 10
0
static svn_error_t *
test_one_long_keyword(const char *keyword,
                      const char *expected,
                      apr_pool_t *pool)
{
  svn_string_t *src_string;
  svn_stream_t *src_stream, *dst_stream;
  svn_stringbuf_t *dst_stringbuf, *src_stringbuf;
  apr_hash_t *keywords = apr_hash_make(pool);
  svn_string_t *expanded = svn_string_create("abcdefg", pool);

  svn_hash_sets(keywords, keyword, expanded);

  /* Expand */
  src_string = svn_string_createf(pool, "$%s$", keyword);
  src_stream = svn_stream_from_string(src_string, pool);
  dst_stringbuf = svn_stringbuf_create_empty(pool);
  dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           TRUE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, expected);

  /* Unexpand */
  src_stringbuf = dst_stringbuf;
  src_stream = svn_stream_from_stringbuf(src_stringbuf, pool);
  dst_stringbuf = svn_stringbuf_create_empty(pool);
  dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           FALSE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, src_string->data);

  return SVN_NO_ERROR;
}
Esempio n. 11
0
/* Print dumpstream-formatted information about REVISION.
 * Implements the `svn_ra_replay_revstart_callback_t' interface.
 */
static svn_error_t *
replay_revstart(svn_revnum_t revision,
                void *replay_baton,
                const svn_delta_editor_t **editor,
                void **edit_baton,
                apr_hash_t *rev_props,
                apr_pool_t *pool)
{
    struct replay_baton *rb = replay_baton;
    apr_hash_t *normal_props;
    svn_stringbuf_t *propstring;
    svn_stream_t *stdout_stream;
    svn_stream_t *revprop_stream;

    SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

    /* Revision-number: 19 */
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_REVISION_NUMBER
                              ": %ld\n", revision));
    SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool));
    propstring = svn_stringbuf_create_ensure(0, pool);
    revprop_stream = svn_stream_from_stringbuf(propstring, pool);
    SVN_ERR(svn_hash_write2(normal_props, revprop_stream, "PROPS-END", pool));
    SVN_ERR(svn_stream_close(revprop_stream));

    /* Prop-content-length: 13 */
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n", propstring->len));

    /* Content-length: 29 */
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n\n", propstring->len));

    /* Property data. */
    SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
                             &(propstring->len)));

    SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));
    SVN_ERR(svn_stream_close(stdout_stream));

    SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision,
                                       rb->stdout_stream, rb->extra_ra_session,
                                       check_cancel, NULL, pool));

    return SVN_NO_ERROR;
}
Esempio n. 12
0
static svn_error_t *
test_stream_seek_stringbuf(apr_pool_t *pool)
{
  svn_stream_t *stream;
  svn_stringbuf_t *stringbuf;
  char buf[4];
  apr_size_t len;
  svn_stream_mark_t *mark;

  stringbuf = svn_stringbuf_create("OneTwo", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One");
  SVN_ERR(svn_stream_mark(stream, &mark, pool));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");
  SVN_ERR(svn_stream_seek(stream, mark));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");

  /* Go back to the begin of last word and try to skip some of it */
  SVN_ERR(svn_stream_seek(stream, mark));
  SVN_ERR(svn_stream_skip(stream, 2));
  /* The remaining line should be empty */
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[len] = '\0';
  SVN_TEST_ASSERT(len == 1);
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Esempio n. 13
0
static svn_error_t *
test_svn_subst_truncated_keywords(apr_pool_t *pool)
{
  svn_string_t *src_string
    = svn_string_create("$Qq: "
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "012345678901234567890123456789012345678901234567"
                        " $", pool);
  svn_stream_t *src_stream = svn_stream_from_string(src_string, pool);
  svn_stringbuf_t *dst_stringbuf = svn_stringbuf_create_empty(pool);
  svn_stream_t *dst_stream = svn_stream_from_stringbuf(dst_stringbuf, pool);
  apr_hash_t *keywords = apr_hash_make(pool);
  svn_string_t *expanded
    = svn_string_create("01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "01234567890123456789012345678901234567890123456789"
                        "012345678901234567890123456789012345678901234567"
                        "xxxxxxxxxx",
                        pool);

  /* The source is already at the maximum length. */
  SVN_TEST_ASSERT(src_string->len == SVN_KEYWORD_MAX_LEN);

  svn_hash_sets(keywords, "Qq", expanded);
  dst_stream = svn_subst_stream_translated(dst_stream, NULL, FALSE, keywords,
                                           TRUE, pool);
  SVN_ERR(svn_stream_copy3(src_stream, dst_stream, NULL, NULL, pool));

  /* The expanded value would make the keyword longer than the maximum
     allowed so it must be truncated; the remaining part of the
     expanded value is the same as the source. */
  SVN_TEST_STRING_ASSERT(dst_stringbuf->data, src_string->data);

  return SVN_NO_ERROR;
}
Esempio n. 14
0
/* Print a revision record header for REVISION to STDOUT_STREAM.  Use
 * SESSION to contact the repository for revision properties and
 * such.
 */
static svn_error_t *
dump_revision_header(svn_ra_session_t *session,
                     svn_stream_t *stdout_stream,
                     svn_revnum_t revision,
                     apr_pool_t *pool)
{
    apr_hash_t *prophash;
    svn_stringbuf_t *propstring;
    svn_stream_t *propstream;

    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_REVISION_NUMBER
                              ": %ld\n", revision));

    prophash = apr_hash_make(pool);
    propstring = svn_stringbuf_create_empty(pool);
    SVN_ERR(svn_ra_rev_proplist(session, revision, &prophash, pool));

    propstream = svn_stream_from_stringbuf(propstring, pool);
    SVN_ERR(svn_hash_write2(prophash, propstream, "PROPS-END", pool));
    SVN_ERR(svn_stream_close(propstream));

    /* Property-content-length: 14; Content-length: 14 */
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n",
                              propstring->len));
    SVN_ERR(svn_stream_printf(stdout_stream, pool,
                              SVN_REPOS_DUMPFILE_CONTENT_LENGTH
                              ": %" APR_SIZE_T_FMT "\n\n",
                              propstring->len));
    /* The properties */
    SVN_ERR(svn_stream_write(stdout_stream, propstring->data,
                             &(propstring->len)));
    SVN_ERR(svn_stream_printf(stdout_stream, pool, "\n"));

    return SVN_NO_ERROR;
}
Esempio n. 15
0
/* fonction simulant la commande svn cat */  
apr_array_header_t *svn_support_cat_call(char *file_path, 
                                         int revision, 
                                         apr_pool_t *subpool){
  svn_error_t *err;
  svn_opt_revision_t rev;
  svn_stream_t *out;
  
  // -- Initialisation de la révision --
  if (revision != -1) {
    rev.kind = svn_opt_revision_number;
    rev.value.number = revision;
  }
  else 
    rev.kind = svn_opt_revision_unspecified;
 
  // -- Initialisation du tableau et du buffer de résultats -- 
  apr_array_header_t *list_result = apr_array_make(subpool, 1, sizeof (const char *));
  svn_stringbuf_t *res = svn_stringbuf_create("",subpool);	
  
  // -- Initialisation du flux de sortie --
  out = svn_stream_from_stringbuf(res,subpool);
  
  err = svn_client_cat2(out, 
                        file_path,
                        &rev,
                        &rev,
                        ctx,
                        subpool);
  if (err) {
    svn_handle_error2 (err, stderr, FALSE, "svn_support_cat: ");
    svn_pool_destroy(subpool);
    return NULL;
  }

  svn_cstring_split_endline_append(list_result,res->data,subpool);
  svn_pool_destroy(subpool);
  return list_result;
}
Esempio n. 16
0
  std::string
  Client::cat(const Path & path,
              const Revision & revision,
              const Revision & peg_revision) throw(ClientException)
  {
    Pool pool;

    svn_stringbuf_t * stringbuf = svn_stringbuf_create("", pool);
    svn_stream_t * stream = svn_stream_from_stringbuf(stringbuf, pool);

    svn_error_t * error;
    error = svn_client_cat2(stream,
                            path.c_str(),
                            peg_revision.revision(),
                            revision.revision(),
                            *m_context,
                            pool);

    if (error != 0)
      throw ClientException(error);

    return std::string(stringbuf->data, stringbuf->len);
  }
Esempio n. 17
0
/* 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? */
}
Esempio n. 18
0
/* This test doesn't test much unless run under valgrind when it
   triggers the problem reported here:

   http://mail-archives.apache.org/mod_mbox/subversion-dev/201202.mbox/%[email protected]%3E

   The two data writes caused the base 64 code to allocate a buffer
   that was a byte short but exactly matched a stringbuf blocksize.
   That meant the stringbuf didn't overallocate and a write beyond
   the end of the buffer occurred.
 */
static svn_error_t *
test_stream_base64_2(apr_pool_t *pool)
{
  const struct data_t {
    const char *encoded1;
    const char *encoded2;
  } data[] = {
    {
      "MTI",
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "A23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "B23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "C23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "D23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "E23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "F23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "G23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "H23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "I23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D123456789E"
      "623456789A123456789B123456789C123456789D123456789E"
      "723456789A123456789B123456789C123456789D123456789E"
      "823456789A123456789B123456789C123456789D123456789E"
      "923456789A123456789B123456789C123456789D123456789E"
      "J23456789A123456789B123456789C123456789D123456789E"
      "123456789A123456789B123456789C123456789D123456789E"
      "223456789A123456789B123456789C123456789D123456789E"
      "323456789A123456789B123456789C123456789D123456789E"
      "423456789A123456789B123456789C123456789D123456789E"
      "523456789A123456789B123456789C123456789D12345"
    },
    {
      NULL,
      NULL,
    },
  };
  int i;

  for (i = 0; data[i].encoded1; i++)
    {
      apr_size_t len1 = strlen(data[i].encoded1);

      svn_stringbuf_t *actual = svn_stringbuf_create_empty(pool);
      svn_stringbuf_t *expected = svn_stringbuf_create_empty(pool);
      svn_stream_t *stream = svn_stream_from_stringbuf(actual, pool);

      stream = svn_base64_encode(stream, pool);
      stream = svn_base64_decode(stream, pool);

      SVN_ERR(svn_stream_write(stream, data[i].encoded1, &len1));
      svn_stringbuf_appendbytes(expected, data[i].encoded1, len1);

      if (data[i].encoded2)
        {
          apr_size_t len2 = strlen(data[i].encoded2);
          SVN_ERR(svn_stream_write(stream, data[i].encoded2, &len2));
          svn_stringbuf_appendbytes(expected, data[i].encoded2, len2);
        }

      SVN_ERR(svn_stream_close(stream));
    }

  return SVN_NO_ERROR;
}
Esempio n. 19
0
static svn_error_t *
test_stream_seek_translated(apr_pool_t *pool)
{
  svn_stream_t *stream, *translated_stream;
  svn_stringbuf_t *stringbuf;
  char buf[44]; /* strlen("One$MyKeyword: my keyword was expanded $Two") + \0 */
  apr_size_t len;
  svn_stream_mark_t *mark;
  apr_hash_t *keywords;
  svn_string_t *keyword_val;

  keywords = apr_hash_make(pool);
  keyword_val = svn_string_create("my keyword was expanded", pool);
  apr_hash_set(keywords, "MyKeyword", APR_HASH_KEY_STRING, keyword_val);
  stringbuf = svn_stringbuf_create("One$MyKeyword$Two", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  translated_stream = svn_subst_stream_translated(stream, APR_EOL_STR,
                                                  FALSE, keywords, TRUE, pool);
  /* Seek from outside of keyword to inside of keyword. */
  len = 25;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 25);
  buf[25] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One$MyKeyword: my keyword");
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  SVN_ERR(svn_stream_reset(translated_stream));
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " was");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "as");

  /* Seek from inside of keyword to inside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 6));
  len = 3;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 3);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "ded");

  /* Seek from inside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Tw");

  /* Seek from outside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 0);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Esempio n. 20
0
static svn_error_t *
test_stream_from_string(apr_pool_t *pool)
{
  int i;
  apr_pool_t *subpool = svn_pool_create(pool);

#define NUM_TEST_STRINGS 4
#define TEST_BUF_SIZE 10

  static const char * const strings[NUM_TEST_STRINGS] = {
    /* 0 */
    "",
    /* 1 */
    "This is a string.",
    /* 2 */
    "This is, by comparison to the previous string, a much longer string.",
    /* 3 */
    "And if you thought that last string was long, you just wait until "
    "I'm finished here.  I mean, how can a string really claim to be long "
    "when it fits on a single line of 80-columns?  Give me a break. "
    "Now, I'm not saying that I'm the longest string out there--far from "
    "it--but I feel that it is safe to assume that I'm far longer than my "
    "peers.  And that demands some amount of respect, wouldn't you say?"
  };

  /* Test svn_stream_from_stringbuf() as a readable stream. */
  for (i = 0; i < NUM_TEST_STRINGS; i++)
    {
      svn_stream_t *stream;
      char buffer[TEST_BUF_SIZE];
      svn_stringbuf_t *inbuf, *outbuf;
      apr_size_t len;

      inbuf = svn_stringbuf_create(strings[i], subpool);
      outbuf = svn_stringbuf_create_empty(subpool);
      stream = svn_stream_from_stringbuf(inbuf, subpool);
      len = TEST_BUF_SIZE;
      while (len == TEST_BUF_SIZE)
        {
          /* Read a chunk ... */
          SVN_ERR(svn_stream_read_full(stream, buffer, &len));

          /* ... and append the chunk to the stringbuf. */
          svn_stringbuf_appendbytes(outbuf, buffer, len);
        }

      if (! svn_stringbuf_compare(inbuf, outbuf))
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "Got unexpected result.");

      svn_pool_clear(subpool);
    }

  /* Test svn_stream_from_stringbuf() as a writable stream. */
  for (i = 0; i < NUM_TEST_STRINGS; i++)
    {
      svn_stream_t *stream;
      svn_stringbuf_t *inbuf, *outbuf;
      apr_size_t amt_read, len;

      inbuf = svn_stringbuf_create(strings[i], subpool);
      outbuf = svn_stringbuf_create_empty(subpool);
      stream = svn_stream_from_stringbuf(outbuf, subpool);
      amt_read = 0;
      while (amt_read < inbuf->len)
        {
          /* Write a chunk ... */
          len = TEST_BUF_SIZE < (inbuf->len - amt_read)
                  ? TEST_BUF_SIZE
                  : inbuf->len - amt_read;
          SVN_ERR(svn_stream_write(stream, inbuf->data + amt_read, &len));
          amt_read += len;
        }

      if (! svn_stringbuf_compare(inbuf, outbuf))
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "Got unexpected result.");

      svn_pool_clear(subpool);
    }

#undef NUM_TEST_STRINGS
#undef TEST_BUF_SIZE

  svn_pool_destroy(subpool);
  return SVN_NO_ERROR;
}
Esempio n. 21
0
svn_error_t *
svn_fs_fs__dag_deserialize(void **out,
                           const char *data,
                           apr_size_t data_len,
                           apr_pool_t *pool)
{
    dag_node_t *node = apr_pcalloc(pool, sizeof(*node));

    if (data_len == 0)
        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                _("Empty noderev in cache"));

    if (*data == 'M')
    {
        const char *newline;
        int id_len;

        data++;
        data_len--;
        if (data_len == 0)
            return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                    _("Kindless noderev in cache"));
        if (*data == 'F')
            node->kind = svn_node_file;
        else if (*data == 'D')
            node->kind = svn_node_dir;
        else
            return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                     _("Unknown kind for noderev in cache: '%c'"),
                                     *data);

        data++;
        data_len--;
        newline = memchr(data, '\n', data_len);
        if (!newline)
            return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                    _("Unterminated ID in cache"));
        id_len = newline - 1 - data;
        node->id = svn_fs_fs__id_parse(data, id_len, pool);
        if (! node->id)
            return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                     _("Bogus ID '%s' in cache"),
                                     apr_pstrndup(pool, data, id_len));

        data += id_len;
        data_len -= id_len;
        data++;
        data_len--;
        if (data_len == 0)
            return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,
                                    _("No created path"));
        node->created_path = apr_pstrndup(pool, data, data_len);
    }
    else if (*data == 'I')
    {
        node_revision_t *noderev;
        apr_pool_t *subpool = svn_pool_create(pool);
        svn_stream_t *stream =
            svn_stream_from_stringbuf(svn_stringbuf_ncreate(data + 1,
                                      data_len - 1,
                                      subpool),
                                      subpool);
        SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool));
        node->kind = noderev->kind;
        node->id = svn_fs_fs__id_copy(noderev->id, pool);
        node->created_path = apr_pstrdup(pool, noderev->created_path);

        if (noderev->is_fresh_txn_root)
            node->fresh_root_predecessor_id = noderev->predecessor_id;

        node->node_revision = noderev;

        svn_pool_destroy(subpool);
    }
    else
        return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                                 _("Unknown node type in cache: '%c'"), *data);

    *out = node;

    return SVN_NO_ERROR;
}
Esempio n. 22
0
inline Try<Diff> diff(const std::string& from, const std::string& to)
{
  // Initialize the Apache Portable Runtime subsystem, as necessary
  // for using the svn library.
  initialize();

  // Note that svn_pool_create wraps apr_pool_create_ex, which is
  // thread safe, see: http://goo.gl/NX0hps.
  apr_pool_t* pool = svn_pool_create(NULL);

  // First we need to produce a text delta stream by diffing 'source'
  // against 'target'.
  svn_string_t source;
  source.data = from.data();
  source.len = from.length();

  svn_string_t target;
  target.data = to.data();
  target.len = to.length();

  svn_txdelta_stream_t* delta;

#if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 8
  svn_txdelta2(
      &delta,
      svn_stream_from_string(&source, pool),
      svn_stream_from_string(&target, pool),
      false,
      pool);
#else
  svn_txdelta(
      &delta,
      svn_stream_from_string(&source, pool),
      svn_stream_from_string(&target, pool),
      pool);
#endif

  // Now we want to convert this text delta stream into an svndiff
  // format based diff. Setup the handler that will consume the text
  // delta and produce the svndiff.
  svn_txdelta_window_handler_t handler;
  void* baton = NULL;
  svn_stringbuf_t* diff = svn_stringbuf_create_ensure(1024, pool);

#if SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 7
  svn_txdelta_to_svndiff3(
      &handler,
      &baton,
      svn_stream_from_stringbuf(diff, pool),
      0,
      SVN_DELTA_COMPRESSION_LEVEL_DEFAULT,
      pool);
#elif SVN_VER_MAJOR >= 1 && SVN_VER_MINOR >= 4
  svn_txdelta_to_svndiff2(
      &handler,
      &baton,
      svn_stream_from_stringbuf(diff, pool),
      0,
      pool);
#else
  svn_txdelta_to_svndiff(
      svn_stream_from_stringbuf(diff, pool),
      pool,
      &handler,
      &baton);
#endif

  // Now feed the text delta to the handler.
  svn_error_t* error = svn_txdelta_send_txstream(delta, handler, baton, pool);

  if (error != NULL) {
    char buffer[1024];
    std::string message(svn_err_best_message(error, buffer, 1024));
    svn_pool_destroy(pool);
    return Error(message);
  }

  Diff d(std::string(diff->data, diff->len));

  svn_pool_destroy(pool);

  return d;
}
Esempio n. 23
0
static svn_error_t *
test_stream_compressed(apr_pool_t *pool)
{
#define NUM_TEST_STRINGS 5
#define TEST_BUF_SIZE 10
#define GENERATED_SIZE 20000

  int i;
  svn_stringbuf_t *bufs[NUM_TEST_STRINGS];
  apr_pool_t *subpool = svn_pool_create(pool);

  static const char * const strings[NUM_TEST_STRINGS - 1] = {
    /* 0 */
    "",
    /* 1 */
    "This is a string.",
    /* 2 */
    "This is, by comparison to the previous string, a much longer string.",
    /* 3 */
    "And if you thought that last string was long, you just wait until "
    "I'm finished here.  I mean, how can a string really claim to be long "
    "when it fits on a single line of 80-columns?  Give me a break. "
    "Now, I'm not saying that I'm the longest string out there--far from "
    "it--but I feel that it is safe to assume that I'm far longer than my "
    "peers.  And that demands some amount of respect, wouldn't you say?"
  };


  for (i = 0; i < (NUM_TEST_STRINGS - 1); i++)
    bufs[i] = svn_stringbuf_create(strings[i], pool);

  /* the last buffer is for the generated data */
  bufs[NUM_TEST_STRINGS - 1] = generate_test_bytes(GENERATED_SIZE, pool);

  for (i = 0; i < NUM_TEST_STRINGS; i++)
    {
      svn_stream_t *stream;
      svn_stringbuf_t *origbuf, *inbuf, *outbuf;
      char buf[TEST_BUF_SIZE];
      apr_size_t len;

      origbuf = bufs[i];
      inbuf = svn_stringbuf_create_empty(subpool);
      outbuf = svn_stringbuf_create_empty(subpool);

      stream = svn_stream_compressed(svn_stream_from_stringbuf(outbuf,
                                                               subpool),
                                     subpool);
      len = origbuf->len;
      SVN_ERR(svn_stream_write(stream, origbuf->data, &len));
      SVN_ERR(svn_stream_close(stream));

      stream = svn_stream_compressed(svn_stream_from_stringbuf(outbuf,
                                                               subpool),
                                     subpool);
      len = TEST_BUF_SIZE;
      while (len >= TEST_BUF_SIZE)
        {
          len = TEST_BUF_SIZE;
          SVN_ERR(svn_stream_read_full(stream, buf, &len));
          if (len > 0)
            svn_stringbuf_appendbytes(inbuf, buf, len);
        }

      if (! svn_stringbuf_compare(inbuf, origbuf))
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "Got unexpected result.");

      SVN_ERR(svn_stream_close(stream));

      svn_pool_clear(subpool);
    }

#undef NUM_TEST_STRINGS
#undef TEST_BUF_SIZE
#undef GENERATED_SIZE

  svn_pool_destroy(subpool);
  return SVN_NO_ERROR;
}