Esempio n. 1
0
static svn_error_t * version(svn_boolean_t quiet, apr_pool_t *pool)
{
  const char *fs_desc_start
    = _("The following repository back-end (FS) modules are available:\n\n");

  svn_stringbuf_t *version_footer;

  version_footer = svn_stringbuf_create(fs_desc_start, pool);
  SVN_ERR(svn_fs_print_modules(version_footer, pool));

#ifdef SVN_HAVE_SASL
  svn_stringbuf_appendcstr(version_footer,
                           _("\nCyrus SASL authentication is available.\n"));
#endif

  return svn_opt_print_help3(NULL, "svnserve", TRUE, quiet, version_footer->data,
                             NULL, NULL, NULL, NULL, NULL, pool);
}
Esempio n. 2
0
/* Implements svn_ra_neon__startelm_cb_t. */
static svn_error_t *
start_207_element(int *elem, void *baton, int parent,
                  const char *nspace, const char *name, const char **atts)
{
  multistatus_baton_t *b = baton;
  const svn_ra_neon__xml_elm_t *elm =
    svn_ra_neon__lookup_xml_elem(multistatus_elements, nspace, name);
  *elem = elm ? validate_element(parent, elm->id) : SVN_RA_NEON__XML_DECLINE;


  if (parent == ELEM_prop)
    {
      svn_stringbuf_setempty(b->propname);
      if (strcmp(nspace, SVN_DAV_PROP_NS_SVN) == 0)
        svn_stringbuf_set(b->propname, SVN_PROP_PREFIX);
      else if (strcmp(nspace, "DAV:") == 0)
        svn_stringbuf_set(b->propname, "DAV:");

      svn_stringbuf_appendcstr(b->propname, name);
    }

  if (*elem < 1) /* ! > 0 */
    return SVN_NO_ERROR;

  switch (*elem)
    {
    case ELEM_propstat:
      b->in_propstat = TRUE;
      b->propstat_has_error = FALSE;
      break;

    default:
      break;
    }

  /* We're guaranteed to have ELM now: SVN_RA_NEON__XML_DECLINE < 1 */
  if (elm->flags & SVN_RA_NEON__XML_CDATA)
    {
      svn_stringbuf_setempty(b->cdata);
      b->want_cdata = b->cdata;
    }

  return SVN_NO_ERROR;
}
Esempio n. 3
0
/* Escape all non-ascii or control characters similar to
 * svn_xml_fuzzy_escape() and svn_utf_cstring_from_utf8_fuzzy().
 * All of the encoding formats somewhat overlap with ascii (BMPString
 * and UniversalString are actually always wider so you'll end up
 * with a bunch of escaped nul bytes, but ideally we don't get here
 * for those).  The result is always a nul-terminated C string. */
static const char *
fuzzy_escape(const svn_string_t *src, apr_pool_t *result_pool)
{
  const char *end = src->data + src->len;
  const char *p = src->data, *q;
  svn_stringbuf_t *outstr;
  char escaped_char[6]; /* ? \ u u u \0 */

  for (q = p; q < end; q++)
    {
      if (!svn_ctype_isascii(*q) || svn_ctype_iscntrl(*q))
        break;
    }

  if (q == end)
    return src->data;

  outstr = svn_stringbuf_create_empty(result_pool);
  while (1)
    {
      q = p;

      /* Traverse till either unsafe character or eos. */
      while (q < end && svn_ctype_isascii(*q) && !svn_ctype_iscntrl(*q))
        q++;

      /* copy chunk before marker */
      svn_stringbuf_appendbytes(outstr, p, q - p);

      if (q == end)
        break;

      apr_snprintf(escaped_char, sizeof(escaped_char), "?\\%03u",
                   (unsigned char) *q);
      svn_stringbuf_appendcstr(outstr, escaped_char);

      p = q + 1;
    }

  return outstr->data;
}
Esempio n. 4
0
static svn_error_t *
test4(const char **msg,
      svn_boolean_t msg_only,
      svn_test_opts_t *opts,
      apr_pool_t *pool)
{
  *msg = "append C string to svn_stringbuf_t";

  if (msg_only)
    return SVN_NO_ERROR;

  a = svn_stringbuf_create(phrase_1, pool);
  svn_stringbuf_appendcstr(a, "new bytes to append");

  /* Test that length, data, and null-termination are correct. */
  if (svn_stringbuf_compare
      (a, svn_stringbuf_create("hello, new bytes to append", pool)))
    return SVN_NO_ERROR;
  else
    return fail(pool, "test failed");
}
Esempio n. 5
0
/* construct the repos-local name for the given DAV property name */
static void
get_repos_propname(dav_db *db,
                   const dav_prop_name *name,
                   const char **repos_propname)
{
  if (strcmp(name->ns, SVN_DAV_PROP_NS_SVN) == 0)
    {
      /* recombine the namespace ("svn:") and the name. */
      svn_stringbuf_set(db->work, SVN_PROP_PREFIX);
      svn_stringbuf_appendcstr(db->work, name->name);
      *repos_propname = db->work->data;
    }
  else if (strcmp(name->ns, SVN_DAV_PROP_NS_CUSTOM) == 0)
    {
      /* the name of a custom prop is just the name -- no ns URI */
      *repos_propname = name->name;
    }
  else
    {
      *repos_propname = NULL;
    }
}
Esempio n. 6
0
/* Escape only NUL characters from a string that is presumed to
 * be UTF-8 encoded and return a nul-terminated C string. */
static const char *
nul_escape(const svn_string_t *src, apr_pool_t *result_pool)
{
  const char *end = src->data + src->len;
  const char *p = src->data, *q;
  svn_stringbuf_t *outstr;

  for (q = p; q < end; q++)
    {
      if (*q == '\0')
        break;
    }

  if (q == end)
    return src->data;

  outstr = svn_stringbuf_create_empty(result_pool);
  while (1)
    {
      q = p;

      /* Traverse till either unsafe character or eos. */
      while (q < end && *q != '\0')
        q++;

      /* copy chunk before marker */
      svn_stringbuf_appendbytes(outstr, p, q - p);

      if (q == end)
        break;

      svn_stringbuf_appendcstr(outstr, "?\\000");

      p = q + 1;
    }

  return outstr->data;
}
Esempio n. 7
0
svn_error_t *
svn_fs_print_modules(svn_stringbuf_t *output,
                     apr_pool_t *pool)
{
  const struct fs_type_defn *defn = fs_modules;
  fs_library_vtable_t *vtable;
  apr_pool_t *iterpool = svn_pool_create(pool);

  while (defn)
    {
      char *line;
      svn_error_t *err;

      svn_pool_clear(iterpool);

      err = get_library_vtable_direct(&vtable, defn, iterpool);
      if (err)
        {
          if (err->apr_err == SVN_ERR_FS_UNKNOWN_FS_TYPE)
            {
              svn_error_clear(err);
              defn = defn->next;
              continue;
            }
          else
            return err;
        }

      line = apr_psprintf(iterpool, "* fs_%s : %s\n",
                          defn->fsap_name, vtable->get_description());
      svn_stringbuf_appendcstr(output, line);
      defn = defn->next;
    }

  svn_pool_destroy(iterpool);

  return SVN_NO_ERROR;
}
Esempio n. 8
0
/* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP.
   If no variable replacements are done, set *OPT_X_VALUEP to
   NULL. Allocate from X_POOL. */
static void
expand_option_value(svn_config_t *cfg, cfg_section_t *section,
                    const char *opt_value, const char **opt_x_valuep,
                    apr_pool_t *x_pool)
{
  svn_stringbuf_t *buf = NULL;
  const char *parse_from = opt_value;
  const char *copy_from = parse_from;
  const char *name_start, *name_end;

  while (parse_from != NULL
         && *parse_from != '\0'
         && (name_start = strstr(parse_from, FMT_START)) != NULL)
    {
      name_start += FMT_START_LEN;
      if (*name_start == '\0')
        /* FMT_START at end of opt_value. */
        break;

      name_end = strstr(name_start, FMT_END);
      if (name_end != NULL)
        {
          cfg_option_t *x_opt;
          apr_size_t len = name_end - name_start;
          char *name = apr_pstrmemdup(x_pool, name_start, len);

          x_opt = find_option(cfg, section->name, name, NULL);

          if (x_opt != NULL)
            {
              const char *cstring;

              /* Pass back the sub-pool originally provided by
                 make_string_from_option() as an indication of when it
                 should terminate. */
              make_string_from_option(&cstring, cfg, section, x_opt, x_pool);

              /* Append the plain text preceding the expansion. */
              len = name_start - FMT_START_LEN - copy_from;
              if (buf == NULL)
                {
                  buf = svn_stringbuf_ncreate(copy_from, len, x_pool);
                  cfg->x_values = TRUE;
                }
              else
                svn_stringbuf_appendbytes(buf, copy_from, len);

              /* Append the expansion and adjust parse pointers. */
              svn_stringbuf_appendcstr(buf, cstring);
              parse_from = name_end + FMT_END_LEN;
              copy_from = parse_from;
            }
          else
            /* Though ConfigParser considers the failure to resolve
               the requested expansion an exception condition, we
               consider it to be plain text, and look for the start of
               the next one. */
            parse_from = name_end + FMT_END_LEN;
        }
      else
        /* Though ConfigParser treats unterminated format specifiers
           as an exception condition, we consider them to be plain
           text.  The fact that there are no more format specifier
           endings means we're done parsing. */
        parse_from = NULL;
    }

  if (buf != NULL)
    {
      /* Copy the remainder of the plain text. */
      svn_stringbuf_appendcstr(buf, copy_from);
      *opt_x_valuep = buf->data;
    }
  else
    *opt_x_valuep = NULL;
}
Esempio n. 9
0
/* Helper function for run_hook_cmd().  Wait for a hook to finish
   executing and return either SVN_NO_ERROR if the hook script completed
   without error, or an error describing the reason for failure.

   NAME and CMD are the name and path of the hook program, CMD_PROC
   is a pointer to the structure representing the running process,
   and READ_ERRHANDLE is an open handle to the hook's stderr.

   Hooks are considered to have failed if we are unable to wait for the
   process, if we are unable to read from the hook's stderr, if the
   process has failed to exit cleanly (due to a coredump, for example),
   or if the process returned a non-zero return code.

   Any error output returned by the hook's stderr will be included in an
   error message, though the presence of output on stderr is not itself
   a reason to fail a hook. */
static svn_error_t *
check_hook_result(const char *name, const char *cmd, apr_proc_t *cmd_proc,
                  apr_file_t *read_errhandle, apr_pool_t *pool)
{
  svn_error_t *err, *err2;
  svn_stringbuf_t *native_stderr, *failure_message;
  const char *utf8_stderr;
  int exitcode;
  apr_exit_why_e exitwhy;

  err2 = svn_stringbuf_from_aprfile(&native_stderr, read_errhandle, pool);

  err = svn_io_wait_for_cmd(cmd_proc, cmd, &exitcode, &exitwhy, pool);
  if (err)
    {
      svn_error_clear(err2);
      return svn_error_trace(err);
    }

  if (APR_PROC_CHECK_EXIT(exitwhy) && exitcode == 0)
    {
      /* The hook exited cleanly.  However, if we got an error reading
         the hook's stderr, fail the hook anyway, because this might be
         symptomatic of a more important problem. */
      if (err2)
        {
          return svn_error_createf
            (SVN_ERR_REPOS_HOOK_FAILURE, err2,
             _("'%s' hook succeeded, but error output could not be read"),
             name);
        }

      return SVN_NO_ERROR;
    }

  /* The hook script failed. */

  /* If we got the stderr output okay, try to translate it into UTF-8.
     Ensure there is something sensible in the UTF-8 string regardless. */
  if (!err2)
    {
      err2 = svn_utf_cstring_to_utf8(&utf8_stderr, native_stderr->data, pool);
      if (err2)
        utf8_stderr = _("[Error output could not be translated from the "
                        "native locale to UTF-8.]");
    }
  else
    {
      utf8_stderr = _("[Error output could not be read.]");
    }
  /*### It would be nice to include the text of any translation or read
        error in the messages above before we clear it here. */
  svn_error_clear(err2);

  if (!APR_PROC_CHECK_EXIT(exitwhy))
    {
      failure_message = svn_stringbuf_createf(pool,
        _("'%s' hook failed (did not exit cleanly: "
          "apr_exit_why_e was %d, exitcode was %d).  "),
        name, exitwhy, exitcode);
    }
  else
    {
      const char *action;
      if (strcmp(name, "start-commit") == 0
          || strcmp(name, "pre-commit") == 0)
        action = _("Commit");
      else if (strcmp(name, "pre-revprop-change") == 0)
        action = _("Revprop change");
      else if (strcmp(name, "pre-lock") == 0)
        action = _("Lock");
      else if (strcmp(name, "pre-unlock") == 0)
        action = _("Unlock");
      else
        action = NULL;
      if (action == NULL)
        failure_message = svn_stringbuf_createf(
            pool, _("%s hook failed (exit code %d)"),
            name, exitcode);
      else
        failure_message = svn_stringbuf_createf(
            pool, _("%s blocked by %s hook (exit code %d)"),
            action, name, exitcode);
    }

  if (utf8_stderr[0])
    {
      svn_stringbuf_appendcstr(failure_message,
                               _(" with output:\n"));
      svn_stringbuf_appendcstr(failure_message, utf8_stderr);
    }
  else
    {
      svn_stringbuf_appendcstr(failure_message,
                               _(" with no output."));
    }

  return svn_error_create(SVN_ERR_REPOS_HOOK_FAILURE, err,
                          failure_message->data);
}
Esempio n. 10
0
svn_error_t *
svn_ra_neon__do_proppatch(svn_ra_neon__session_t *ras,
                          const char *url,
                          apr_hash_t *prop_changes,
                          apr_array_header_t *prop_deletes,
                          apr_hash_t *extra_headers,
                          apr_pool_t *pool)
{
  svn_error_t *err;
  svn_stringbuf_t *body;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* just punt if there are no changes to make. */
  if ((prop_changes == NULL || (! apr_hash_count(prop_changes)))
      && (prop_deletes == NULL || prop_deletes->nelts == 0))
    return SVN_NO_ERROR;

  /* easier to roll our own PROPPATCH here than use ne_proppatch(), which
   * doesn't really do anything clever. */
  body = svn_stringbuf_create
    ("<?xml version=\"1.0\" encoding=\"utf-8\" ?>" DEBUG_CR
     "<D:propertyupdate xmlns:D=\"DAV:\" xmlns:V=\""
     SVN_DAV_PROP_NS_DAV "\" xmlns:C=\""
     SVN_DAV_PROP_NS_CUSTOM "\" xmlns:S=\""
     SVN_DAV_PROP_NS_SVN "\">" DEBUG_CR, pool);

  /* Handle property changes. */
  if (prop_changes)
    {
      apr_hash_index_t *hi;
      svn_stringbuf_appendcstr(body, "<D:set><D:prop>");
      for (hi = apr_hash_first(pool, prop_changes); hi; hi = apr_hash_next(hi))
        {
          const void *key;
          void *val;
          svn_pool_clear(subpool);
          apr_hash_this(hi, &key, NULL, &val);
          append_setprop(body, key, val, subpool);
        }
      svn_stringbuf_appendcstr(body, "</D:prop></D:set>");
    }

  /* Handle property deletions. */
  if (prop_deletes)
    {
      int n;
      svn_stringbuf_appendcstr(body, "<D:remove><D:prop>");
      for (n = 0; n < prop_deletes->nelts; n++)
        {
          const char *name = APR_ARRAY_IDX(prop_deletes, n, const char *);
          svn_pool_clear(subpool);
          append_setprop(body, name, NULL, subpool);
        }
      svn_stringbuf_appendcstr(body, "</D:prop></D:remove>");
    }
  svn_pool_destroy(subpool);

  /* Finish up the body. */
  svn_stringbuf_appendcstr(body, "</D:propertyupdate>");

  /* Finish up the headers. */
  if (! extra_headers)
    extra_headers = apr_hash_make(pool);
  apr_hash_set(extra_headers, "Content-Type", APR_HASH_KEY_STRING,
               "text/xml; charset=UTF-8");

  err = svn_ra_neon__simple_request(NULL, ras, "PROPPATCH", url,
                                    extra_headers, body->data,
                                    200, 207, pool);
  if (err)
    return svn_error_create
      (SVN_ERR_RA_DAV_PROPPATCH_FAILED, err,
       _("At least one property change failed; repository is unchanged"));

  return SVN_NO_ERROR;
}
Esempio n. 11
0
svn_error_t *
svn_cl__get_log_message(const char **log_msg,
                        const char **tmp_file,
                        const apr_array_header_t *commit_items,
                        void *baton,
                        apr_pool_t *pool)
{
  svn_stringbuf_t *default_msg = NULL;
  struct log_msg_baton *lmb = baton;
  svn_stringbuf_t *message = NULL;

  /* Set default message.  */
  default_msg = svn_stringbuf_create(APR_EOL_STR, pool);
  svn_stringbuf_appendcstr(default_msg, EDITOR_EOF_PREFIX);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR APR_EOL_STR);

  *tmp_file = NULL;
  if (lmb->message)
    {
      svn_stringbuf_t *log_msg_buf = svn_stringbuf_create(lmb->message, pool);
      svn_string_t *log_msg_str = apr_pcalloc(pool, sizeof(*log_msg_str));

      /* Trim incoming messages of the EOF marker text and the junk
         that follows it.  */
      truncate_buffer_at_prefix(&(log_msg_buf->len), log_msg_buf->data,
                                EDITOR_EOF_PREFIX);

      /* Make a string from a stringbuf, sharing the data allocation. */
      log_msg_str->data = log_msg_buf->data;
      log_msg_str->len = log_msg_buf->len;
      SVN_ERR_W(svn_subst_translate_string2(&log_msg_str, FALSE, FALSE,
                                            log_msg_str, lmb->message_encoding,
                                            FALSE, pool, pool),
                _("Error normalizing log message to internal format"));

      *log_msg = log_msg_str->data;
      return SVN_NO_ERROR;
    }

  if (! commit_items->nelts)
    {
      *log_msg = "";
      return SVN_NO_ERROR;
    }

  while (! message)
    {
      /* We still don't have a valid commit message.  Use $EDITOR to
         get one.  Note that svn_cl__edit_externally will still return
         a UTF-8'ized log message. */
      int i;
      svn_stringbuf_t *tmp_message = svn_stringbuf_dup(default_msg, pool);
      svn_error_t *err = SVN_NO_ERROR;
      svn_string_t *msg_string = svn_string_create("", pool);

      for (i = 0; i < commit_items->nelts; i++)
        {
          svn_client_commit_item3_t *item
            = APR_ARRAY_IDX(commit_items, i, svn_client_commit_item3_t *);
          const char *path = item->path;
          char text_mod = '_', prop_mod = ' ', unlock = ' ';

          if (! path)
            path = item->url;
          else if (! *path)
            path = ".";

          if (! svn_path_is_url(path) && lmb->base_dir)
            path = svn_dirent_is_child(lmb->base_dir, path, pool);

          /* If still no path, then just use current directory. */
          if (! path)
            path = ".";

          if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
              && (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
            text_mod = 'R';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
            text_mod = 'A';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
            text_mod = 'D';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS)
            text_mod = 'M';

          if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_PROP_MODS)
            prop_mod = 'M';

          if (! lmb->keep_locks
              && item->state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
            unlock = 'U';

          svn_stringbuf_appendbyte(tmp_message, text_mod);
          svn_stringbuf_appendbyte(tmp_message, prop_mod);
          svn_stringbuf_appendbyte(tmp_message, unlock);
          if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
            /* History included via copy/move. */
            svn_stringbuf_appendcstr(tmp_message, "+ ");
          else
            svn_stringbuf_appendcstr(tmp_message, "  ");
          svn_stringbuf_appendcstr(tmp_message, path);
          svn_stringbuf_appendcstr(tmp_message, APR_EOL_STR);
        }

      msg_string->data = tmp_message->data;
      msg_string->len = tmp_message->len;

      /* Use the external edit to get a log message. */
      if (! lmb->non_interactive)
        {
          err = svn_cl__edit_string_externally(&msg_string, &lmb->tmpfile_left,
                                               lmb->editor_cmd, lmb->base_dir,
                                               msg_string, "svn-commit",
                                               lmb->config, TRUE,
                                               lmb->message_encoding,
                                               pool);
        }
      else /* non_interactive flag says we can't pop up an editor, so error */
        {
          return svn_error_create
            (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
             _("Cannot invoke editor to get log message "
               "when non-interactive"));
        }

      /* Dup the tmpfile path into its baton's pool. */
      *tmp_file = lmb->tmpfile_left = apr_pstrdup(lmb->pool,
                                                  lmb->tmpfile_left);

      /* If the edit returned an error, handle it. */
      if (err)
        {
          if (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR)
            err = svn_error_quick_wrap
              (err, _("Could not use external editor to fetch log message; "
                      "consider setting the $SVN_EDITOR environment variable "
                      "or using the --message (-m) or --file (-F) options"));
          return svn_error_trace(err);
        }

      if (msg_string)
        message = svn_stringbuf_create_from_string(msg_string, pool);

      /* Strip the prefix from the buffer. */
      if (message)
        truncate_buffer_at_prefix(&message->len, message->data,
                                  EDITOR_EOF_PREFIX);

      if (message)
        {
          /* We did get message, now check if it is anything more than just
             white space as we will consider white space only as empty */
          apr_size_t len;

          for (len = 0; len < message->len; len++)
            {
              /* FIXME: should really use an UTF-8 whitespace test
                 rather than svn_ctype_isspace, which is ASCII only */
              if (! svn_ctype_isspace(message->data[len]))
                break;
            }
          if (len == message->len)
            message = NULL;
        }

      if (! message)
        {
          const char *reply;
          SVN_ERR(svn_cmdline_prompt_user2
                  (&reply,
                   _("\nLog message unchanged or not specified\n"
                     "(a)bort, (c)ontinue, (e)dit:\n"), NULL, pool));
          if (reply)
            {
              int letter = apr_tolower(reply[0]);

              /* If the user chooses to abort, we cleanup the
                 temporary file and exit the loop with a NULL
                 message. */
              if ('a' == letter)
                {
                  SVN_ERR(svn_io_remove_file2(lmb->tmpfile_left, FALSE, pool));
                  *tmp_file = lmb->tmpfile_left = NULL;
                  break;
                }

              /* If the user chooses to continue, we make an empty
                 message, which will cause us to exit the loop.  We
                 also cleanup the temporary file. */
              if ('c' == letter)
                {
                  SVN_ERR(svn_io_remove_file2(lmb->tmpfile_left, FALSE, pool));
                  *tmp_file = lmb->tmpfile_left = NULL;
                  message = svn_stringbuf_create("", pool);
                }

              /* If the user chooses anything else, the loop will
                 continue on the NULL message. */
            }
        }
    }

  *log_msg = message ? message->data : NULL;
  return SVN_NO_ERROR;
}
Esempio n. 12
0
/* Remove r0 references from the mergeinfo string *STR.
 *
 * r0 was never a valid mergeinfo reference and cannot be committed with
 * recent servers, but can be committed through a server older than 1.6.18
 * for HTTP or older than 1.6.17 for the other protocols. See issue #4476
 * "Mergeinfo containing r0 makes svnsync and dump and load fail".
 *
 * Set *WAS_CHANGED to TRUE if *STR was changed, otherwise to FALSE.
 */
static svn_error_t *
remove_r0_mergeinfo(const svn_string_t **str,
                    svn_boolean_t *was_changed,
                    apr_pool_t *result_pool,
                    apr_pool_t *scratch_pool)
{
  svn_stringbuf_t *new_str = svn_stringbuf_create_empty(result_pool);
  apr_array_header_t *lines;
  int i;

  SVN_ERR_ASSERT(*str && (*str)->data);

  *was_changed = FALSE;

  /* for each line */
  lines = svn_cstring_split((*str)->data, "\n", FALSE, scratch_pool);

  for (i = 0; i < lines->nelts; i++)
    {
      char *line = APR_ARRAY_IDX(lines, i, char *);
      char *colon;
      char *rangelist;

      /* split at the last colon */
      colon = strrchr(line, ':');

      if (! colon)
        return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL,
                                 _("Missing colon in svn:mergeinfo "
                                   "property"));

      rangelist = colon + 1;

      /* remove r0 */
      if (colon[1] == '0')
        {
          if (strncmp(rangelist, "0*,", 3) == 0)
            {
              rangelist += 3;
            }
          else if (strcmp(rangelist, "0*") == 0
                   || strncmp(rangelist, "0,", 2) == 0
                   || strncmp(rangelist, "0-1*", 4) == 0
                   || strncmp(rangelist, "0-1,", 4) == 0
                   || strcmp(rangelist, "0-1") == 0)
            {
              rangelist += 2;
            }
          else if (strcmp(rangelist, "0") == 0)
            {
              rangelist += 1;
            }
          else if (strncmp(rangelist, "0-", 2) == 0)
            {
              rangelist[0] = '1';
            }
        }

      /* reassemble */
      if (rangelist[0])
        {
          if (new_str->len)
            svn_stringbuf_appendbyte(new_str, '\n');
          svn_stringbuf_appendbytes(new_str, line, colon + 1 - line);
          svn_stringbuf_appendcstr(new_str, rangelist);
        }
    }

  if (strcmp((*str)->data, new_str->data) != 0)
    {
      *was_changed = TRUE;
    }

  *str = svn_stringbuf__morph_into_string(new_str);
  return SVN_NO_ERROR;
}
/* Request a mergeinfo-report from the URL attached to SESSION,
   and fill in the CATALOG with the results.  */
svn_error_t *
svn_ra_neon__get_mergeinfo(svn_ra_session_t *session,
                           svn_mergeinfo_catalog_t *catalog,
                           const apr_array_header_t *paths,
                           svn_revnum_t revision,
                           svn_mergeinfo_inheritance_t inherit,
                           svn_boolean_t include_descendants,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
  struct mergeinfo_baton mb;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;

  static const char minfo_report_head[] =
    "<S:" SVN_DAV__MERGEINFO_REPORT " xmlns:S=\"" SVN_XML_NAMESPACE "\">"
    DEBUG_CR;

  static const char minfo_report_tail[] =
    "</S:" SVN_DAV__MERGEINFO_REPORT ">" DEBUG_CR;

  *catalog = NULL;

  /* Construct the request body. */
  svn_stringbuf_appendcstr(request_body, minfo_report_head);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:revision>%ld"
                                        "</S:revision>", revision));
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:inherit>%s"
                                        "</S:inherit>",
                                        svn_inheritance_to_word(inherit)));

  if (include_descendants)
    {
      /* Send it only if true; server will default to "no". */
      svn_stringbuf_appendcstr(request_body,
                               "<S:include-descendants>yes"
                               "</S:include-descendants>");
    }

  if (paths)
    {
      int i;

      for (i = 0; i < paths->nelts; i++)
        {
          const char *this_path =
            apr_xml_quote_string(pool,
                                 ((const char **)paths->elts)[i],
                                 0);
          svn_stringbuf_appendcstr(request_body, "<S:path>");
          svn_stringbuf_appendcstr(request_body, this_path);
          svn_stringbuf_appendcstr(request_body, "</S:path>");
        }
    }

  svn_stringbuf_appendcstr(request_body, minfo_report_tail);

  mb.pool = pool;
  mb.curr_path = svn_stringbuf_create("", pool);
  mb.curr_info = svn_stringbuf_create("", pool);
  mb.catalog = apr_hash_make(pool);
  mb.err = SVN_NO_ERROR;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from END. */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  SVN_ERR(svn_ra_neon__parsed_request(ras,
                                      "REPORT",
                                      final_bc_url,
                                      request_body->data,
                                      NULL, NULL,
                                      start_element,
                                      cdata_handler,
                                      end_element,
                                      &mb,
                                      NULL,
                                      NULL,
                                      FALSE,
                                      pool));

  if (mb.err == SVN_NO_ERROR && apr_hash_count(mb.catalog))
    *catalog = mb.catalog;

  return mb.err;
}
Esempio n. 14
0
File: log.c Progetto: vocho/openqnx
svn_error_t * svn_ra_neon__get_log(svn_ra_session_t *session,
                                   const apr_array_header_t *paths,
                                   svn_revnum_t start,
                                   svn_revnum_t end,
                                   int limit,
                                   svn_boolean_t discover_changed_paths,
                                   svn_boolean_t strict_node_history,
                                   svn_boolean_t include_merged_revisions,
                                   const apr_array_header_t *revprops,
                                   svn_log_entry_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)
{
  /* The Plan: Send a request to the server for a log report.
   * Somewhere in mod_dav_svn, there will be an implementation, R, of
   * the `svn_log_entry_receiver_t' function type.  Some other
   * function in mod_dav_svn will use svn_repos_get_logs() to loop R
   * over the log messages, and the successive invocations of R will
   * collectively transmit the report back here, where we parse the
   * report and invoke RECEIVER (which is an entirely separate
   * instance of `svn_log_entry_receiver_t') on each individual
   * message in that report.
   */

  int i;
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body = svn_stringbuf_create("", pool);
  svn_boolean_t want_custom_revprops;
  struct log_baton lb;
  svn_string_t bc_url, bc_relative;
  const char *final_bc_url;
  svn_revnum_t use_rev;
  svn_error_t *err;

  /* ### todo: I don't understand why the static, file-global
     variables shared by update and status are called `report_head'
     and `report_tail', instead of `request_head' and `request_tail'.
     Maybe Greg can explain?  Meanwhile, I'm tentatively using
     "request_*" for my local vars below. */

  static const char log_request_head[]
    = "<S:log-report xmlns:S=\"" SVN_XML_NAMESPACE "\">" DEBUG_CR;

  static const char log_request_tail[] = "</S:log-report>" DEBUG_CR;

  /* Construct the request body. */
  svn_stringbuf_appendcstr(request_body, log_request_head);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:start-revision>%ld"
                                        "</S:start-revision>", start));
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:end-revision>%ld"
                                        "</S:end-revision>", end));
  if (limit)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:limit>%d</S:limit>", limit));
    }

  if (discover_changed_paths)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:discover-changed-paths/>"));
    }

  if (strict_node_history)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:strict-node-history/>"));
    }

  if (include_merged_revisions)
    {
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:include-merged-revisions/>"));
    }

  if (revprops)
    {
      lb.want_author = lb.want_date = lb.want_message = FALSE;
      want_custom_revprops = FALSE;
      for (i = 0; i < revprops->nelts; i++)
        {
          char *name = APR_ARRAY_IDX(revprops, i, char *);
          svn_stringbuf_appendcstr(request_body, "<S:revprop>");
          svn_stringbuf_appendcstr(request_body, name);
          svn_stringbuf_appendcstr(request_body, "</S:revprop>");
          if (strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0)
            lb.want_author = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_DATE) == 0)
            lb.want_date = TRUE;
          else if (strcmp(name, SVN_PROP_REVISION_LOG) == 0)
            lb.want_message = TRUE;
          else
            want_custom_revprops = TRUE;
        }
    }
  else
    {
Esempio n. 15
0
File: log.c Progetto: 2asoft/freebsd
const char *
svn_log__log(const apr_array_header_t *paths,
             svn_revnum_t start, svn_revnum_t end,
             int limit, svn_boolean_t discover_changed_paths,
             svn_boolean_t strict_node_history,
             svn_boolean_t include_merged_revisions,
             const apr_array_header_t *revprops, apr_pool_t *pool)
{
  int i;
  apr_pool_t *iterpool = svn_pool_create(pool);
  svn_stringbuf_t *space_separated_paths = svn_stringbuf_create_empty(pool);
  svn_stringbuf_t *options = svn_stringbuf_create_empty(pool);

  for (i = 0; i < paths->nelts; i++)
    {
      const char *path = APR_ARRAY_IDX(paths, i, const char *);
      svn_pool_clear(iterpool);
      if (i != 0)
        svn_stringbuf_appendcstr(space_separated_paths, " ");
      svn_stringbuf_appendcstr(space_separated_paths,
                               svn_path_uri_encode(path, iterpool));
    }

  if (limit)
    {
      const char *tmp = apr_psprintf(pool, " limit=%d", limit);
      svn_stringbuf_appendcstr(options, tmp);
    }
  if (discover_changed_paths)
    svn_stringbuf_appendcstr(options, " discover-changed-paths");
  if (strict_node_history)
    svn_stringbuf_appendcstr(options, " strict");
  if (include_merged_revisions)
    svn_stringbuf_appendcstr(options,
                        log_include_merged_revisions(include_merged_revisions));
  if (revprops == NULL)
    svn_stringbuf_appendcstr(options, " revprops=all");
  else if (revprops->nelts > 0)
    {
      svn_stringbuf_appendcstr(options, " revprops=(");
      for (i = 0; i < revprops->nelts; i++)
        {
          const char *name = APR_ARRAY_IDX(revprops, i, const char *);
          svn_pool_clear(iterpool);
          if (i != 0)
            svn_stringbuf_appendcstr(options, " ");
          svn_stringbuf_appendcstr(options, svn_path_uri_encode(name,
                                                                iterpool));
        }
      svn_stringbuf_appendcstr(options, ")");
    }
Esempio n. 16
0
static svn_error_t *
parse_list(const char **msg,
           svn_boolean_t msg_only,
           svn_test_opts_t *opts,
           apr_pool_t *pool)
{
  *msg = "parse lists";

  if (msg_only)
    return SVN_NO_ERROR;

  {
    /* Try lists of varying length.  */
    int list_len;

    for (list_len = 0;
         list_len < 30;
         list_len < 4 ? list_len++ : (list_len *= 3))
      {
        /* Try lists with different separators.  */
        int sep;

        for (sep = 0; sep < 256; sep++)
          if (skel_is_space( (apr_byte_t)sep))
            {
              /* Try lists with different numbers of separator
                 characters between the elements.  */
              int sep_count;

              for (sep_count = 0;
                   sep_count < 30;
                   sep_count < 4 ? sep_count++ : (sep_count *= 3))
                {
                  /* Try various single-byte implicit-length atoms
                     for elements.  */
                  int atom_byte;

                  for (atom_byte = 0; atom_byte < 256; atom_byte++)
                    if (skel_is_name( (apr_byte_t)atom_byte))
                      {
                        int i;
                        svn_stringbuf_t *str = get_empty_string(pool);
                        svn_skel_t *skel;
                        svn_skel_t *child;

                        put_list_start(str,  (apr_byte_t)sep, sep_count);
                        for (i = 0; i < list_len; i++)
                          put_implicit_length_byte(str,
                                                   (apr_byte_t)atom_byte,
                                                   (apr_byte_t)sep);
                        put_list_end(str,  (apr_byte_t)sep, sep_count);

                        skel = parse_str(str, pool);
                        if (! check_list(skel, list_len))
                          return fail(pool, "couldn't parse list");
                        for (child = skel->children;
                             child;
                             child = child->next)
                          if (! check_implicit_length_byte
                                 (child, (apr_byte_t)atom_byte))
                            return fail(pool,
                                        "list was reparsed incorrectly");
                      }

                  /* Try the atom containing every character that's
                     legal in an implicit-length atom as the element.  */
                  {
                    int i;
                    svn_stringbuf_t *str = get_empty_string(pool);
                    svn_skel_t *skel;
                    svn_skel_t *child;

                    put_list_start(str,  (apr_byte_t)sep, sep_count);
                    for (i = 0; i < list_len; i++)
                      put_implicit_length_all_chars(str,  (apr_byte_t)sep);
                    put_list_end(str,  (apr_byte_t)sep, sep_count);

                    skel = parse_str(str, pool);
                    if (! check_list(skel, list_len))
                      return fail(pool, "couldn't parse list");
                    for (child = skel->children;
                         child;
                         child = child->next)
                      if (! check_implicit_length_all_chars(child))
                        return fail(pool, "couldn't parse list");
                  }

                  /* Try using every one-byte explicit-length atom as
                     an element.  */
                  for (atom_byte = 0; atom_byte < 256; atom_byte++)
                    {
                      int i;
                      svn_stringbuf_t *str = get_empty_string(pool);
                      svn_skel_t *skel;
                      svn_skel_t *child;
                      char buf[1];

                      buf[0] = atom_byte;

                      put_list_start(str,  (apr_byte_t)sep, sep_count);
                      for (i = 0; i < list_len; i++)
                        put_explicit_length(str, buf, 1,  (apr_byte_t)sep);
                      put_list_end(str,  (apr_byte_t)sep, sep_count);

                      skel = parse_str(str, pool);
                      if (! check_list(skel, list_len))
                        return fail(pool, "couldn't parse list");
                      for (child = skel->children;
                           child;
                           child = child->next)
                        if (! check_explicit_length(child, buf, 1))
                          return fail(pool, "list was reparsed incorrectly");
                    }

                  /* Try using an atom containing every character as
                     an element.  */
                  {
                    int i;
                    svn_stringbuf_t *str = get_empty_string(pool);
                    svn_skel_t *skel;
                    svn_skel_t *child;
                    char data[256];

                    for (i = 0; i < 256; i++)
                      data[i] = i;

                    put_list_start(str,  (apr_byte_t)sep, sep_count);
                    for (i = 0; i < list_len; i++)
                      put_explicit_length(str, data, 256,  (apr_byte_t)sep);
                    put_list_end(str,  (apr_byte_t)sep, sep_count);

                    skel = parse_str(str, pool);
                    if (! check_list(skel, list_len))
                      return fail(pool, "couldn't parse list");
                    for (child = skel->children;
                         child;
                         child = child->next)
                      if (! check_explicit_length(child, data, 256))
                        return fail(pool, "list was re-parsed incorrectly");
                  }
                }
            }
      }
  }

  /* Try to parse some invalid lists.  */
  {
    int sep;

    /* Try different separators.  */
    for (sep = 0; sep < 256; sep++)
      if (skel_is_space( (apr_byte_t)sep))
        {
          /* Try lists with different numbers of separator
             characters between the elements.  */
          int sep_count;

          for (sep_count = 0;
               sep_count < 100;
               sep_count < 10 ? sep_count++ : (sep_count *= 3))
            {
              svn_stringbuf_t *str;

              /* A list with only a separator.  */
              str = get_empty_string(pool);
              put_list_start(str,  (apr_byte_t)sep, sep_count);
              if (parse_str(str, pool))
                return fail(pool, "failed to detect syntax error");

              /* A list with only a terminator.  */
              str = get_empty_string(pool);
              put_list_end(str,  (apr_byte_t)sep, sep_count);
              if (parse_str(str, pool))
                return fail(pool, "failed to detect syntax error");

              /* A list containing an invalid element.  */
              str = get_empty_string(pool);
              put_list_start(str,  (apr_byte_t)sep, sep_count);
              svn_stringbuf_appendcstr(str, "100 ");
              put_list_end(str,  (apr_byte_t)sep, sep_count);
              if (parse_str(str, pool))
                return fail(pool, "failed to detect invalid element");
            }
        }
  }

  return SVN_NO_ERROR;
}
Esempio n. 17
0
svn_error_t * svn_ra_neon__get_props(apr_hash_t **results,
                                     svn_ra_neon__session_t *sess,
                                     const char *url,
                                     int depth,
                                     const char *label,
                                     const ne_propname *which_props,
                                     apr_pool_t *pool)
{
  propfind_ctx_t pc;
  svn_stringbuf_t *body;
  apr_hash_t *extra_headers = apr_hash_make(pool);

  svn_ra_neon__add_depth_header(extra_headers, depth);

  /* If we have a label, use it. */
  if (label != NULL)
    apr_hash_set(extra_headers, "Label", 5, label);

  /* It's easier to roll our own PROPFIND here than use neon's current
     interfaces. */
  /* The start of the request body is fixed: */
  body = svn_stringbuf_create
    ("<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
     "<propfind xmlns=\"DAV:\">" DEBUG_CR, pool);

  /* Are we asking for specific propert(y/ies), or just all of them? */
  if (which_props)
    {
      int n;
      apr_pool_t *iterpool = svn_pool_create(pool);

      svn_stringbuf_appendcstr(body, "<prop>" DEBUG_CR);
      for (n = 0; which_props[n].name != NULL; n++)
        {
          svn_pool_clear(iterpool);
          svn_stringbuf_appendcstr
            (body, apr_pstrcat(iterpool, "<", which_props[n].name, " xmlns=\"",
                               which_props[n].nspace, "\"/>" DEBUG_CR, NULL));
        }
      svn_stringbuf_appendcstr(body, "</prop></propfind>" DEBUG_CR);
      svn_pool_destroy(iterpool);
    }
  else
    {
      svn_stringbuf_appendcstr(body, "<allprop/></propfind>" DEBUG_CR);
    }

  /* Initialize our baton. */
  memset(&pc, 0, sizeof(pc));
  pc.pool = pool;
  pc.propbuffer = apr_hash_make(pool);
  pc.props = apr_hash_make(pool);
  pc.cdata = svn_stringbuf_create("", pool);

  /* Create and dispatch the request! */
  SVN_ERR(svn_ra_neon__parsed_request(sess, "PROPFIND", url,
                                      body->data, 0,
                                      set_parser,
                                      start_element,
                                      svn_ra_neon__xml_collect_cdata,
                                      end_element,
                                      &pc, extra_headers, NULL, FALSE, pool));

  *results = pc.props;
  return SVN_NO_ERROR;
}
svn_error_t *
svn_ra_neon__get_locations(svn_ra_session_t *session,
                           apr_hash_t **locations,
                           const char *relative_path,
                           svn_revnum_t peg_revision,
                           const apr_array_header_t *location_revisions,
                           apr_pool_t *pool)
{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_locations_baton_t request_baton;
  const char *relative_path_quoted;
  const char *bc_url;
  const char *bc_relative;
  const char *final_bc_url;
  int i;
  int status_code = 0;

  *locations = apr_hash_make(pool);

  request_body = svn_stringbuf_create("", pool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>" DEBUG_CR
                           "<S:get-locations xmlns:S=\"" SVN_XML_NAMESPACE
                           "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  svn_stringbuf_appendcstr(request_body, "<S:path>");
  /* We need to escape the path XML-wise. */
  relative_path_quoted = apr_xml_quote_string(pool, relative_path, 0);
  svn_stringbuf_appendcstr(request_body, relative_path_quoted);
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);
  svn_stringbuf_appendcstr(request_body,
                           apr_psprintf(pool,
                                        "<S:peg-revision>%ld"
                                        "</S:peg-revision>" DEBUG_CR,
                                        peg_revision));

  for (i = 0; i < location_revisions->nelts; ++i)
    {
      svn_revnum_t rev = APR_ARRAY_IDX(location_revisions, i, svn_revnum_t);
      svn_stringbuf_appendcstr(request_body,
                               apr_psprintf(pool,
                                            "<S:location-revision>%ld"
                                            "</S:location-revision>" DEBUG_CR,
                                            rev));
    }

  svn_stringbuf_appendcstr(request_body, "</S:get-locations>");

  request_baton.ras = ras;
  request_baton.hash = *locations;
  request_baton.pool = pool;

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the peg revision.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision, pool));
  final_bc_url = svn_path_url_add_component2(bc_url, bc_relative, pool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", final_bc_url,
                                    request_body->data, NULL, NULL,
                                    gloc_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, pool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"), "get-locations");

  return err;
}
Esempio n. 19
0
static svn_error_t *
test_strings(const svn_test_opts_t *opts,
             apr_pool_t *pool)
{
  struct string_args args;
  svn_fs_t *fs;
  svn_stringbuf_t *string;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_bdb_fs
          (&fs, "test-repo-test-strings", opts,
           pool));

  /* The plan (after each step below, verify the size and contents of
     the string):

     1.  Write a new string (string1).
     2.  Append string2 to string.
     3.  Clear string.
     4.  Append string3 to string.
     5.  Delete string (verify by size requested failure).
     6.  Write a new string (string1), appending string2, string3, and
         string4.
  */

  /* 1. Write a new string (string1). */
  args.fs = fs;
  args.key = NULL;
  args.text = bigstring1;
  args.len = strlen(bigstring1);
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
                                 FALSE, pool));

  /* Make sure a key was returned. */
  if (! args.key)
    return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                            "write of new string failed to return new key");

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
                                 FALSE, pool));

  /* Append a second string to our first one. */
  args.text = bigstring2;
  args.len = strlen(bigstring2);
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
                                 FALSE, pool));

  /* Verify record's size and contents. */
  string = svn_stringbuf_create(bigstring1, pool);
  svn_stringbuf_appendcstr(string, bigstring2);
  args.text = string->data;
  args.len = string->len;
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
                                 FALSE, pool));

  /* Clear the record */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_clear, &args,
                                 FALSE, pool));

  /* Verify record's size and contents. */
  args.text = "";
  args.len = 0;
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
                                 FALSE, pool));

  /* Append a third string to our first one. */
  args.text = bigstring3;
  args.len = strlen(bigstring3);
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_append, &args,
                                 FALSE, pool));

  /* Verify record's size and contents. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_verify_string, &args,
                                 FALSE, pool));

  /* Delete our record...she's served us well. */
  SVN_ERR(svn_fs_base__retry_txn(args.fs, txn_body_string_delete, &args,
                                 FALSE, pool));

  /* Now, we expect a size request on this record to fail with
     SVN_ERR_FS_NO_SUCH_STRING. */
  {
    svn_error_t *err = svn_fs_base__retry_txn(args.fs, txn_body_string_size,
                                              &args, FALSE, pool);

    if (! err)
      return svn_error_create(SVN_ERR_FS_GENERAL, NULL,
                              "query unexpectedly successful");
    if (err->apr_err != SVN_ERR_FS_NO_SUCH_STRING)
      return svn_error_create(SVN_ERR_FS_GENERAL, err,
                              "query failed with unexpected error");
    svn_error_clear(err);
  }

  return SVN_NO_ERROR;
}
Esempio n. 20
0
/* Edit CHUNK and return the result in *MERGED_CHUNK allocated in POOL. */
static svn_error_t *
edit_chunk(apr_array_header_t **merged_chunk,
           apr_array_header_t *chunk,
           const char *editor_cmd,
           apr_hash_t *config,
           apr_pool_t *result_pool,
           apr_pool_t *scratch_pool)
{
  apr_file_t *temp_file;
  const char *temp_file_name;
  int i;
  apr_off_t pos;
  svn_boolean_t eof;
  svn_error_t *err;
  apr_pool_t *iterpool;

  SVN_ERR(svn_io_open_unique_file3(&temp_file, &temp_file_name, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   scratch_pool, scratch_pool));
  iterpool = svn_pool_create(scratch_pool);
  for (i = 0; i < chunk->nelts; i++)
    {
      svn_stringbuf_t *line = APR_ARRAY_IDX(chunk, i, svn_stringbuf_t *);
      apr_size_t bytes_written;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_io_file_write_full(temp_file, line->data, line->len,
                                     &bytes_written, iterpool));
      if (line->len != bytes_written)
        return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL,
                                _("Could not write data to temporary file"));
    }
  SVN_ERR(svn_io_file_flush(temp_file, scratch_pool));

  err = svn_cmdline__edit_file_externally(temp_file_name, editor_cmd,
                                          config, scratch_pool);
  if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR))
    {
      svn_error_t *root_err = svn_error_root_cause(err);

      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
                                  root_err->message ? root_err->message :
                                  _("No editor found.")));
      svn_error_clear(err);
      *merged_chunk = NULL;
      svn_pool_destroy(iterpool);
      return SVN_NO_ERROR;
    }
  else if (err && (err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
    {
      svn_error_t *root_err = svn_error_root_cause(err);

      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
                                  root_err->message ? root_err->message :
                                  _("Error running editor.")));
      svn_error_clear(err);
      *merged_chunk = NULL;
      svn_pool_destroy(iterpool);
      return SVN_NO_ERROR;
    }
  else if (err)
    return svn_error_trace(err);

  *merged_chunk = apr_array_make(result_pool, 1, sizeof(svn_stringbuf_t *));
  pos = 0;
  SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &pos, scratch_pool));
  do
    {
      svn_stringbuf_t *line;
      const char *eol_str;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_io_file_readline(temp_file, &line, &eol_str, &eof,
                                   APR_SIZE_MAX, result_pool, iterpool));
      if (eol_str)
        svn_stringbuf_appendcstr(line, eol_str);

      APR_ARRAY_PUSH(*merged_chunk, svn_stringbuf_t *) = line;
    }
  while (!eof);
  svn_pool_destroy(iterpool);

  SVN_ERR(svn_io_file_close(temp_file, scratch_pool));

  return SVN_NO_ERROR;
}
Esempio n. 21
0
/* Write a single change entry, path PATH, change CHANGE, to STREAM.

   Only include the node kind field if INCLUDE_NODE_KIND is true.  Only
   include the mergeinfo-mod field if INCLUDE_MERGEINFO_MODS is true.
   All temporary allocations are in SCRATCH_POOL. */
static svn_error_t *
write_change_entry(svn_stream_t *stream,
                   const char *path,
                   svn_fs_path_change2_t *change,
                   svn_boolean_t include_node_kind,
                   svn_boolean_t include_mergeinfo_mods,
                   apr_pool_t *scratch_pool)
{
  const char *idstr;
  const char *change_string = NULL;
  const char *kind_string = "";
  const char *mergeinfo_string = "";
  svn_stringbuf_t *buf;
  apr_size_t len;

  switch (change->change_kind)
    {
    case svn_fs_path_change_modify:
      change_string = ACTION_MODIFY;
      break;
    case svn_fs_path_change_add:
      change_string = ACTION_ADD;
      break;
    case svn_fs_path_change_delete:
      change_string = ACTION_DELETE;
      break;
    case svn_fs_path_change_replace:
      change_string = ACTION_REPLACE;
      break;
    case svn_fs_path_change_reset:
      change_string = ACTION_RESET;
      break;
    default:
      return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,
                               _("Invalid change type %d"),
                               change->change_kind);
    }

  if (change->node_rev_id)
    idstr = svn_fs_fs__id_unparse(change->node_rev_id, scratch_pool)->data;
  else
    idstr = ACTION_RESET;

  if (include_node_kind)
    {
      SVN_ERR_ASSERT(change->node_kind == svn_node_dir
                     || change->node_kind == svn_node_file);
      kind_string = apr_psprintf(scratch_pool, "-%s",
                                 change->node_kind == svn_node_dir
                                 ? SVN_FS_FS__KIND_DIR
                                  : SVN_FS_FS__KIND_FILE);
    }

  if (include_mergeinfo_mods && change->mergeinfo_mod != svn_tristate_unknown)
    mergeinfo_string = apr_psprintf(scratch_pool, " %s",
                                    change->mergeinfo_mod == svn_tristate_true
                                      ? FLAG_TRUE
                                      : FLAG_FALSE);

  buf = svn_stringbuf_createf(scratch_pool, "%s %s%s %s %s%s %s\n",
                              idstr, change_string, kind_string,
                              change->text_mod ? FLAG_TRUE : FLAG_FALSE,
                              change->prop_mod ? FLAG_TRUE : FLAG_FALSE,
                              mergeinfo_string,
                              path);

  if (SVN_IS_VALID_REVNUM(change->copyfrom_rev))
    {
      svn_stringbuf_appendcstr(buf, apr_psprintf(scratch_pool, "%ld %s",
                                                 change->copyfrom_rev,
                                                 change->copyfrom_path));
    }

   svn_stringbuf_appendbyte(buf, '\n');

   /* Write all change info in one write call. */
   len = buf->len;
   return svn_error_trace(svn_stream_write(stream, buf->data, &len));
}
Esempio n. 22
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__help(apr_getopt_t *os,
             void *baton,
             apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = NULL;
  svn_stringbuf_t *version_footer = NULL;

  /* xgettext: the %s is for SVN_VER_NUMBER. */
  char help_header_template[] =
  N_("usage: svn <subcommand> [options] [args]\n"
     "Subversion command-line client, version %s.\n"
     "Type 'svn help <subcommand>' for help on a specific subcommand.\n"
     "Type 'svn --version' to see the program version and RA modules\n"
     "  or 'svn --version --quiet' to see just the version number.\n"
     "\n"
     "Most subcommands take file and/or directory arguments, recursing\n"
     "on the directories.  If no arguments are supplied to such a\n"
     "command, it recurses on the current directory (inclusive) by default.\n"
     "\n"
     "Available subcommands:\n");

  char help_footer[] =
  N_("Subversion is a tool for version control.\n"
     "For additional information, see http://subversion.apache.org/\n");

  char *help_header =
    apr_psprintf(pool, _(help_header_template), SVN_VER_NUMBER);

  const char *ra_desc_start
    = _("The following repository access (RA) modules are available:\n\n");

  if (baton)
    {
      svn_cl__cmd_baton_t *const cmd_baton = baton;
#ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
      /* Windows never actually stores plaintext passwords, it
         encrypts the contents using CryptoAPI. ...

         ... If CryptoAPI is available ... but it should be on all
         versions of Windows that are even remotely interesting two
         days before the scheduled end of the world, when this comment
         is being written. */
#  ifndef WIN32
      svn_boolean_t store_auth_creds =
        SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
      svn_boolean_t store_passwords =
        SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
      svn_boolean_t store_plaintext_passwords = FALSE;
      svn_config_t *cfg;

      if (cmd_baton->ctx->config)
        {
          cfg = svn_hash_gets(cmd_baton->ctx->config,
                              SVN_CONFIG_CATEGORY_CONFIG);
          if (cfg)
            {
              SVN_ERR(svn_config_get_bool(cfg, &store_auth_creds,
                                          SVN_CONFIG_SECTION_AUTH,
                                          SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
                                          store_auth_creds));
              SVN_ERR(svn_config_get_bool(cfg, &store_passwords,
                                          SVN_CONFIG_SECTION_AUTH,
                                          SVN_CONFIG_OPTION_STORE_PASSWORDS,
                                          store_passwords));
            }
          cfg = svn_hash_gets(cmd_baton->ctx->config,
                              SVN_CONFIG_CATEGORY_SERVERS);
          if (cfg)
            {
              const char *value;
              SVN_ERR(svn_config_get_yes_no_ask
                      (cfg, &value,
                       SVN_CONFIG_SECTION_GLOBAL,
                       SVN_CONFIG_OPTION_STORE_PLAINTEXT_PASSWORDS,
                       SVN_CONFIG_DEFAULT_OPTION_STORE_PLAINTEXT_PASSWORDS));
              if (0 == svn_cstring_casecmp(value, SVN_CONFIG_TRUE))
                store_plaintext_passwords = TRUE;
            }
        }

      if (store_plaintext_passwords && store_auth_creds && store_passwords)
        {
          version_footer = svn_stringbuf_create(
              _("WARNING: Plaintext password storage is enabled!\n\n"),
              pool);
          svn_stringbuf_appendcstr(version_footer, ra_desc_start);
        }
#  endif /* !WIN32 */
#endif /* !SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE */

      opt_state = cmd_baton->opt_state;
    }

  if (!version_footer)
    version_footer = svn_stringbuf_create(ra_desc_start, pool);
  SVN_ERR(svn_ra_print_modules(version_footer, pool));

  return svn_opt_print_help4(os,
                             "svn",   /* ### erm, derive somehow? */
                             opt_state ? opt_state->version : FALSE,
                             opt_state ? opt_state->quiet : FALSE,
                             opt_state ? opt_state->verbose : FALSE,
                             version_footer->data,
                             help_header,   /* already gettext()'d */
                             svn_cl__cmd_table,
                             svn_cl__options,
                             svn_cl__global_options,
                             _(help_footer),
                             pool);
}
Esempio n. 23
0
svn_error_t *
svn_cl__get_log_message(const char **log_msg,
                        const char **tmp_file,
                        const apr_array_header_t *commit_items,
                        void *baton,
                        apr_pool_t *pool)
{
  svn_stringbuf_t *default_msg = NULL;
  struct log_msg_baton *lmb = baton;
  svn_stringbuf_t *message = NULL;
  svn_config_t *cfg;
  const char *mfc_after, *sponsored_by;

  cfg = lmb->config ? svn_hash_gets(lmb->config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;

  /* Set default message.  */
  default_msg = svn_stringbuf_create(APR_EOL_STR, pool);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "PR:\t\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Submitted by:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Reported by:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Reviewed by:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Approved by:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Obtained from:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "MFC after:\t");
  svn_config_get(cfg, &mfc_after, SVN_CONFIG_SECTION_MISCELLANY, "freebsd-mfc-after", NULL);
  if (mfc_after != NULL)
	  svn_stringbuf_appendcstr(default_msg, mfc_after);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "MFH:\t\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Relnotes:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Security:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Sponsored by:\t");
  svn_config_get(cfg, &sponsored_by, SVN_CONFIG_SECTION_MISCELLANY, "freebsd-sponsored-by",
#ifdef HAS_ORGANIZATION_NAME
  	ORGANIZATION_NAME);
#else
	NULL);
#endif
  if (sponsored_by != NULL)
	  svn_stringbuf_appendcstr(default_msg, sponsored_by);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "Differential Revision:\t" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, EDITOR_EOF_PREFIX);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Description of fields to fill in above:                     76 columns --|" APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> PR:                       If and which Problem Report is related." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Submitted by:             If someone else sent in the change." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Reported by:              If someone else reported the issue." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Reviewed by:              If someone else reviewed your modification." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Approved by:              If you needed approval for this commit." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Obtained from:            If the change is from a third party." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> MFC after:                N [day[s]|week[s]|month[s]].  Request a reminder email." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> MFH:                      Ports tree branch name.  Request approval for merge." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Relnotes:                 Set to 'yes' for mention in release notes." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Security:                 Vulnerability reference (one per line) or description." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Sponsored by:             If the change was sponsored by an organization." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Differential Revision:    https://reviews.freebsd.org/D### (*full* phabric URL needed)." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, "> Empty fields above will be automatically removed." APR_EOL_STR);
  svn_stringbuf_appendcstr(default_msg, APR_EOL_STR);

  *tmp_file = NULL;
  if (lmb->message)
    {
      svn_string_t *log_msg_str = svn_string_create(lmb->message, pool);

      SVN_ERR_W(svn_subst_translate_string2(&log_msg_str, NULL, NULL,
                                            log_msg_str, lmb->message_encoding,
                                            FALSE, pool, pool),
                _("Error normalizing log message to internal format"));

      /* Strip off the EOF marker text and the junk that follows it. */
      truncate_buffer_at_prefix(&(log_msg_str->len), (char *)log_msg_str->data,
                                EDITOR_EOF_PREFIX);

      cleanmsg(&(log_msg_str->len), (char*)log_msg_str->data);

      *log_msg = log_msg_str->data;
      return SVN_NO_ERROR;
    }

  if (! commit_items->nelts)
    {
      *log_msg = "";
      return SVN_NO_ERROR;
    }

  while (! message)
    {
      /* We still don't have a valid commit message.  Use $EDITOR to
         get one.  Note that svn_cl__edit_string_externally will still
         return a UTF-8'ized log message. */
      int i;
      svn_stringbuf_t *tmp_message = svn_stringbuf_dup(default_msg, pool);
      svn_error_t *err = SVN_NO_ERROR;
      svn_string_t *msg_string = svn_string_create_empty(pool);

      for (i = 0; i < commit_items->nelts; i++)
        {
          svn_client_commit_item3_t *item
            = APR_ARRAY_IDX(commit_items, i, svn_client_commit_item3_t *);
          const char *path = item->path;
          char text_mod = '_', prop_mod = ' ', unlock = ' ';

          if (! path)
            path = item->url;
          else if (lmb->base_dir)
            path = svn_dirent_is_child(lmb->base_dir, path, pool);

          /* If still no path, then just use current directory. */
          if (! path || !*path)
            path = ".";

          if ((item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
              && (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
            text_mod = 'R';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
            text_mod = 'A';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
            text_mod = 'D';
          else if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_TEXT_MODS)
            text_mod = 'M';

          if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_PROP_MODS)
            prop_mod = 'M';

          if (! lmb->keep_locks
              && item->state_flags & SVN_CLIENT_COMMIT_ITEM_LOCK_TOKEN)
            unlock = 'U';

          svn_stringbuf_appendbyte(tmp_message, text_mod);
          svn_stringbuf_appendbyte(tmp_message, prop_mod);
          svn_stringbuf_appendbyte(tmp_message, unlock);
          if (item->state_flags & SVN_CLIENT_COMMIT_ITEM_IS_COPY)
            /* History included via copy/move. */
            svn_stringbuf_appendcstr(tmp_message, "+ ");
          else
            svn_stringbuf_appendcstr(tmp_message, "  ");
          svn_stringbuf_appendcstr(tmp_message, path);
          svn_stringbuf_appendcstr(tmp_message, APR_EOL_STR);
        }

      msg_string->data = tmp_message->data;
      msg_string->len = tmp_message->len;

      /* Use the external edit to get a log message. */
      if (! lmb->non_interactive)
        {
          err = svn_cmdline__edit_string_externally(&msg_string, &lmb->tmpfile_left,
                                                    lmb->editor_cmd,
                                                    lmb->base_dir ? lmb->base_dir : "",
                                                    msg_string, "svn-commit",
                                                    lmb->config, TRUE,
                                                    lmb->message_encoding,
                                                    pool);
        }
      else /* non_interactive flag says we can't pop up an editor, so error */
        {
          return svn_error_create
            (SVN_ERR_CL_INSUFFICIENT_ARGS, NULL,
             _("Cannot invoke editor to get log message "
               "when non-interactive"));
        }

      /* Dup the tmpfile path into its baton's pool. */
      *tmp_file = lmb->tmpfile_left = apr_pstrdup(lmb->pool,
                                                  lmb->tmpfile_left);

      /* If the edit returned an error, handle it. */
      if (err)
        {
          if (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR)
            err = svn_error_quick_wrap
              (err, _("Could not use external editor to fetch log message; "
                      "consider setting the $SVN_EDITOR environment variable "
                      "or using the --message (-m) or --file (-F) options"));
          return svn_error_trace(err);
        }

      if (msg_string)
        message = svn_stringbuf_create_from_string(msg_string, pool);

      /* Strip off the EOF marker text and the junk that follows it. */
      if (message)
        truncate_buffer_at_prefix(&message->len, message->data,
                                  EDITOR_EOF_PREFIX);
      /*
       * Since we're adding freebsd-specific tokens to the log message,
       * clean out any leftovers to avoid accidently sending them to other
       * projects that won't be expecting them.
       */
      if (message)
	cleanmsg(&message->len, message->data);

      if (message)
        {
          /* We did get message, now check if it is anything more than just
             white space as we will consider white space only as empty */
          apr_size_t len;

          for (len = 0; len < message->len; len++)
            {
              /* FIXME: should really use an UTF-8 whitespace test
                 rather than svn_ctype_isspace, which is ASCII only */
              if (! svn_ctype_isspace(message->data[len]))
                break;
            }
          if (len == message->len)
            message = NULL;
        }

      if (! message)
        {
          const char *reply;
          SVN_ERR(svn_cmdline_prompt_user2
                  (&reply,
                   _("\nLog message unchanged or not specified\n"
                     "(a)bort, (c)ontinue, (e)dit:\n"), NULL, pool));
          if (reply)
            {
              int letter = apr_tolower(reply[0]);

              /* If the user chooses to abort, we cleanup the
                 temporary file and exit the loop with a NULL
                 message. */
              if ('a' == letter)
                {
                  SVN_ERR(svn_io_remove_file2(lmb->tmpfile_left, FALSE, pool));
                  *tmp_file = lmb->tmpfile_left = NULL;
                  break;
                }

              /* If the user chooses to continue, we make an empty
                 message, which will cause us to exit the loop.  We
                 also cleanup the temporary file. */
              if ('c' == letter)
                {
                  SVN_ERR(svn_io_remove_file2(lmb->tmpfile_left, FALSE, pool));
                  *tmp_file = lmb->tmpfile_left = NULL;
                  message = svn_stringbuf_create_empty(pool);
                }

              /* If the user chooses anything else, the loop will
                 continue on the NULL message. */
            }
        }
    }

  *log_msg = message ? message->data : NULL;
  return SVN_NO_ERROR;
}
Esempio n. 24
0
static svn_error_t *
change_dir_prop(void *dir_baton,
                const char *name,
                const svn_string_t *value,
                apr_pool_t *pool)
{
  node_baton_t *db = dir_baton;
  edit_baton_t *eb = db->edit_baton;

  /* Only regular properties can pass over libsvn_ra */
  if (svn_property_kind2(name) != svn_prop_regular_kind)
    return SVN_NO_ERROR;

  /* Maybe drop svn:mergeinfo.  */
  if (eb->strip_mergeinfo && (strcmp(name, SVN_PROP_MERGEINFO) == 0))
    {
      eb->mergeinfo_stripped = TRUE;
      return SVN_NO_ERROR;
    }

  /* Maybe convert svnmerge-integrated data into svn:mergeinfo.  (We
     ignore svnmerge-blocked for now.) */
  /* ### FIXME: Consult the mirror repository's HEAD prop values and
     ### merge svn:mergeinfo, svnmerge-integrated, and svnmerge-blocked. */
  if (eb->migrate_svnmerge && (strcmp(name, "svnmerge-integrated") == 0))
    {
      if (value)
        {
          /* svnmerge-integrated differs from svn:mergeinfo in a pair
             of ways.  First, it can use tabs, newlines, or spaces to
             delimit source information.  Secondly, the source paths
             are relative URLs, whereas svn:mergeinfo uses relative
             paths (not URI-encoded). */
          svn_error_t *err;
          svn_stringbuf_t *mergeinfo_buf = svn_stringbuf_create_empty(pool);
          svn_mergeinfo_t mergeinfo;
          int i;
          apr_array_header_t *sources =
            svn_cstring_split(value->data, " \t\n", TRUE, pool);
          svn_string_t *new_value;

          for (i = 0; i < sources->nelts; i++)
            {
              const char *rel_path;
              apr_array_header_t *path_revs =
                svn_cstring_split(APR_ARRAY_IDX(sources, i, const char *),
                                  ":", TRUE, pool);

              /* ### TODO: Warn? */
              if (path_revs->nelts != 2)
                continue;

              /* Append this source's mergeinfo data. */
              rel_path = APR_ARRAY_IDX(path_revs, 0, const char *);
              rel_path = svn_path_uri_decode(rel_path, pool);
              svn_stringbuf_appendcstr(mergeinfo_buf, rel_path);
              svn_stringbuf_appendcstr(mergeinfo_buf, ":");
              svn_stringbuf_appendcstr(mergeinfo_buf,
                                       APR_ARRAY_IDX(path_revs, 1,
                                                     const char *));
              svn_stringbuf_appendcstr(mergeinfo_buf, "\n");
            }

          /* Try to parse the mergeinfo string we've created, just to
             check for bogosity.  If all goes well, we'll unparse it
             again and use that as our property value.  */
          err = svn_mergeinfo_parse(&mergeinfo, mergeinfo_buf->data, pool);
          if (err)
            {
              svn_error_clear(err);
              return SVN_NO_ERROR;
            }
          SVN_ERR(svn_mergeinfo_to_string(&new_value, mergeinfo, pool));
          value = new_value;
        }
      name = SVN_PROP_MERGEINFO;
      eb->svnmerge_migrated = TRUE;
    }

  /* Remember if we see any svnmerge-blocked properties. */
  if (eb->migrate_svnmerge && (strcmp(name, "svnmerge-blocked") == 0))
    {
      eb->svnmerge_blocked = TRUE;
    }

  /* Normalize svn:* properties as necessary. */
  if (svn_prop_needs_translation(name))
    {
      svn_boolean_t was_normalized;
      svn_boolean_t mergeinfo_tweaked = FALSE;

      /* Normalize encoding to UTF-8, and EOL style to LF. */
      SVN_ERR(normalize_string(&value, &was_normalized, eb->source_prop_encoding,
                               pool, pool));
      /* Maybe adjust svn:mergeinfo. */
      if (value && strcmp(name, SVN_PROP_MERGEINFO) == 0)
        {
          SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked,
                                      pool, pool));
          if (mergeinfo_tweaked)
            eb->mergeinfo_tweaked = TRUE;
        }
      if (was_normalized)
        (*(eb->normalized_node_props_counter))++;
    }

  return eb->wrapped_editor->change_dir_prop(db->wrapped_node_baton,
                                             name, value, pool);
}
svn_error_t *
svn_ra_neon__get_location_segments(svn_ra_session_t *session,
                                   const char *path,
                                   svn_revnum_t peg_revision,
                                   svn_revnum_t start_rev,
                                   svn_revnum_t end_rev,
                                   svn_location_segment_receiver_t receiver,
                                   void *receiver_baton,
                                   apr_pool_t *pool)

{
  svn_ra_neon__session_t *ras = session->priv;
  svn_stringbuf_t *request_body;
  svn_error_t *err;
  get_location_segments_baton_t request_baton;
  const char *bc_url;
  const char *bc_relative;
  const char *bc;
  int status_code = 0;
  apr_pool_t *subpool = svn_pool_create(pool);

  /* Build the request body. */
  request_body = svn_stringbuf_create("", subpool);
  svn_stringbuf_appendcstr(request_body,
                           "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                           DEBUG_CR "<S:get-location-segments xmlns:S=\""
                           SVN_XML_NAMESPACE "\" xmlns:D=\"DAV:\">" DEBUG_CR);

  /* Tack on the path... */
  svn_stringbuf_appendcstr(request_body, "<S:path>");
  svn_stringbuf_appendcstr(request_body, apr_xml_quote_string(subpool, path, 0));
  svn_stringbuf_appendcstr(request_body, "</S:path>" DEBUG_CR);

  /* ...and maybe a peg revision... */
  if (SVN_IS_VALID_REVNUM(peg_revision))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:peg-revision>%ld</S:peg-revision>"
                                  DEBUG_CR, peg_revision));

  /* ...and maybe a start revision... */
  if (SVN_IS_VALID_REVNUM(start_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:start-revision>%ld</S:start-revision>"
                                  DEBUG_CR, start_rev));

  /* ...and maybe an end revision. */
  if (SVN_IS_VALID_REVNUM(end_rev))
    svn_stringbuf_appendcstr
      (request_body, apr_psprintf(subpool,
                                  "<S:end-revision>%ld</S:end-revision>"
                                  DEBUG_CR, end_rev));

  svn_stringbuf_appendcstr(request_body, "</S:get-location-segments>");

  request_baton.receiver = receiver;
  request_baton.receiver_baton = receiver_baton;
  request_baton.subpool = svn_pool_create(subpool);

  /* ras's URL may not exist in HEAD, and thus it's not safe to send
     it as the main argument to the REPORT request; it might cause
     dav_get_resource() to choke on the server.  So instead, we pass a
     baseline-collection URL, which we get from the PEG_REVISION.  */
  SVN_ERR(svn_ra_neon__get_baseline_info(&bc_url, &bc_relative, NULL, ras,
                                         ras->url->data, peg_revision,
                                         subpool));
  bc = svn_path_url_add_component2(bc_url, bc_relative, subpool);

  err = svn_ra_neon__parsed_request(ras, "REPORT", bc,
                                    request_body->data, NULL, NULL,
                                    gls_start_element, NULL, NULL,
                                    &request_baton, NULL, &status_code,
                                    FALSE, subpool);
  svn_pool_destroy(request_baton.subpool);
  svn_pool_destroy(subpool);

  /* Map status 501: Method Not Implemented to our not implemented error.
     1.0.x servers and older don't support this report. */
  if (status_code == 501)
    return svn_error_createf(SVN_ERR_RA_NOT_IMPLEMENTED, err,
                             _("'%s' REPORT not implemented"),
                             "get-location-segments");

  return err;
}
Esempio n. 26
0
/* Implements svn_ra_neon__endelm_cb_t . */
static svn_error_t *
end_207_element(void *baton, int state,
                const char *nspace, const char *name)
{
  multistatus_baton_t *b = baton;

  switch (state)
    {
    case ELEM_multistatus:
      if (b->contains_error)
        {
          if (svn_stringbuf_isempty(b->description))
            return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                    _("The request response contained at least "
                                      "one error"));
          else if (b->contains_precondition_error)
            return svn_error_create(SVN_ERR_FS_PROP_BASEVALUE_MISMATCH, NULL,
                                    b->description->data);
          else
            return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                    b->description->data);
        }
      break;

    case ELEM_responsedescription:
      if (b->in_propstat)
        svn_stringbuf_set(b->propstat_description, b->cdata->data);
      else
        {
          if (! svn_stringbuf_isempty(b->description))
            svn_stringbuf_appendcstr(b->description, "\n");
          svn_stringbuf_appendstr(b->description, b->cdata);
        }
      break;

    case ELEM_status:
      {
        ne_status status;

        if (ne_parse_statusline(b->cdata->data, &status) == 0)
          {
            /*### I wanted ||=, but I guess the end result is the same */
            if (! b->in_propstat)
              b->contains_error |= (status.klass != 2);
            else
              b->propstat_has_error = (status.klass != 2);

            /* Handle "412 Precondition Failed" specially */
            if (status.code == 412)
              b->contains_precondition_error = TRUE;

            free(status.reason_phrase);
          }
        else
          return svn_error_create(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                                  _("The response contains a non-conforming "
                                    "HTTP status line"));
      }
      break;

    case ELEM_propstat:
      b->in_propstat = FALSE;
      b->contains_error |= b->propstat_has_error;
      svn_stringbuf_appendcstr(b->description,
                               apr_psprintf(b->req->pool,
                                            _("Error setting property '%s': "),
                                            b->propname->data));
      svn_stringbuf_appendstr(b->description,
                              b->propstat_description);

    default:
      /* do nothing */
      break;
    }

  /* When we have an element which wants cdata,
     we'll set it all up in start_207_element() again */
  b->want_cdata = NULL;

  return SVN_NO_ERROR;
}