Example #1
0
void
svn_cl__print_xml_lock(svn_stringbuf_t **sb,
                       const svn_lock_t *lock,
                       apr_pool_t *pool)
{
  /* "<lock>" */
  svn_xml_make_open_tag(sb, pool, svn_xml_normal, "lock", SVN_VA_NULL);

  /* "<token>xx</token>" */
  svn_cl__xml_tagged_cdata(sb, pool, "token", lock->token);

  /* "<owner>xx</owner>" */
  svn_cl__xml_tagged_cdata(sb, pool, "owner", lock->owner);

  /* "<comment>xx</comment>" */
  svn_cl__xml_tagged_cdata(sb, pool, "comment", lock->comment);

  /* "<created>xx</created>" */
  svn_cl__xml_tagged_cdata(sb, pool, "created",
                           svn_time_to_cstring(lock->creation_date, pool));

  /* "<expires>xx</expires>" */
  if (lock->expiration_date != 0)
    svn_cl__xml_tagged_cdata(sb, pool, "expires",
                             svn_time_to_cstring(lock->expiration_date, pool));

  /* "</lock>" */
  svn_xml_make_close_tag(sb, pool, "lock");
}
/* This implements the svn_proplist_receiver_t interface, printing XML to
   stdout. */
static svn_error_t *
proplist_receiver_xml(void *baton,
                      const char *path,
                      apr_hash_t *prop_hash,
                      apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((proplist_baton_t *)baton)->opt_state;
  svn_boolean_t is_url = ((proplist_baton_t *)baton)->is_url;
  svn_stringbuf_t *sb = NULL;
  const char *name_local;

  if (! is_url)
    name_local = svn_dirent_local_style(path, pool);
  else
    name_local = path;

  /* "<target ...>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
                        "path", name_local, NULL);

  SVN_ERR(svn_cl__print_xml_prop_hash(&sb, prop_hash, (! opt_state->verbose),
                                      pool));

  /* "</target>" */
  svn_xml_make_close_tag(&sb, pool, "target");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #3
0
static svn_error_t *
print_properties_xml(const char *pname,
                     apr_hash_t *props,
                     apr_pool_t *pool)
{
  apr_array_header_t *sorted_props;
  int i;
  apr_pool_t *iterpool = svn_pool_create(pool);

  sorted_props = svn_sort__hash(props, svn_sort_compare_items_as_paths, pool);
  for (i = 0; i < sorted_props->nelts; i++)
    {
      svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
      const char *filename = item.key;
      svn_string_t *propval = item.value;
      svn_stringbuf_t *sb = NULL;

      svn_pool_clear(iterpool);

      svn_xml_make_open_tag(&sb, iterpool, svn_xml_normal, "target",
                        "path", filename, NULL);
      svn_cmdline__print_xml_prop(&sb, pname, propval, iterpool);
      svn_xml_make_close_tag(&sb, iterpool, "target");

      SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
    }

  svn_pool_destroy(iterpool);

  return SVN_NO_ERROR;
}
Example #4
0
/* Prints XML target element with path attribute TARGET, using POOL for
   temporary allocations. */
static svn_error_t *
print_start_target_xml(const char *target, apr_pool_t *pool)
{
    svn_stringbuf_t *sb = svn_stringbuf_create("", pool);

    svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "target",
                          "path", target, NULL);

    return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #5
0
svn_error_t *
svn_cl__xml_print_header(const char *tagname,
                         apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);

  /* <?xml version="1.0" encoding="UTF-8"?> */
  svn_xml_make_header2(&sb, "UTF-8", pool);

  /* "<TAGNAME>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, tagname, SVN_VA_NULL);

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #6
0
void
svn_cl__xml_tagged_cdata(svn_stringbuf_t **sb,
                         apr_pool_t *pool,
                         const char *tagname,
                         const char *string)
{
  if (string)
    {
      svn_xml_make_open_tag(sb, pool, svn_xml_protect_pcdata,
                            tagname, SVN_VA_NULL);
      svn_xml_escape_cdata_cstring(sb, string, pool);
      svn_xml_make_close_tag(sb, pool, tagname);
    }
}
Example #7
0
/* Finish a target element by optionally printing an against element if
 * REPOS_REV is a valid revision number, and then printing an target end tag.
 * Use POOL for temporary allocations. */
static svn_error_t *
print_finish_target_xml(svn_revnum_t repos_rev,
                        apr_pool_t *pool)
{
    svn_stringbuf_t *sb = svn_stringbuf_create("", pool);

    if (SVN_IS_VALID_REVNUM(repos_rev))
    {
        const char *repos_rev_str;
        repos_rev_str = apr_psprintf(pool, "%ld", repos_rev);
        svn_xml_make_open_tag(&sb, pool, svn_xml_self_closing, "against",
                              "revision", repos_rev_str, NULL);
    }

    svn_xml_make_close_tag(&sb, pool, "target");

    return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #8
0
void
svn_cl__print_xml_commit(svn_stringbuf_t **sb,
                         svn_revnum_t revision,
                         const char *author,
                         const char *date,
                         apr_pool_t *pool)
{
  /* "<commit ...>" */
  svn_xml_make_open_tag(sb, pool, svn_xml_normal, "commit",
                        "revision",
                        apr_psprintf(pool, "%ld", revision), SVN_VA_NULL);

  /* "<author>xx</author>" */
  if (author)
    svn_cl__xml_tagged_cdata(sb, pool, "author", author);

  /* "<date>xx</date>" */
  if (date)
    svn_cl__xml_tagged_cdata(sb, pool, "date", date);

  /* "</commit>" */
  svn_xml_make_close_tag(sb, pool, "commit");
}
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__proplist(apr_getopt_t *os,
                 void *baton,
                 apr_pool_t *scratch_pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_array_header_t *targets;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE,
                                                      scratch_pool));

  /* Add "." if user passed 0 file arguments */
  svn_opt_push_implicit_dot_target(targets, scratch_pool);

  if (opt_state->revprop)  /* operate on revprops */
    {
      svn_revnum_t rev;
      const char *URL;
      apr_hash_t *proplist;

      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
                                      &URL, ctx, scratch_pool));

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_list(&proplist,
                                      URL, &(opt_state->start_revision),
                                      &rev, ctx, scratch_pool));

      if (opt_state->xml)
        {
          svn_stringbuf_t *sb = NULL;
          char *revstr = apr_psprintf(scratch_pool, "%ld", rev);

          SVN_ERR(svn_cl__xml_print_header("properties", scratch_pool));

          svn_xml_make_open_tag(&sb, scratch_pool, svn_xml_normal,
                                "revprops",
                                "rev", revstr, NULL);
          SVN_ERR(svn_cl__print_xml_prop_hash
                  (&sb, proplist, (! opt_state->verbose), scratch_pool));
          svn_xml_make_close_tag(&sb, scratch_pool, "revprops");

          SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
          SVN_ERR(svn_cl__xml_print_footer("properties", scratch_pool));
        }
      else
        {
          SVN_ERR
            (svn_cmdline_printf(scratch_pool,
                                _("Unversioned properties on revision %ld:\n"),
                                rev));

          SVN_ERR(svn_cl__print_prop_hash
                  (NULL, proplist, (! opt_state->verbose), scratch_pool));
        }
    }
  else  /* operate on normal, versioned properties (not revprops) */
    {
      int i;
      apr_pool_t *iterpool;
      svn_proplist_receiver_t pl_receiver;
      svn_boolean_t had_errors = FALSE;

      if (opt_state->xml)
        {
          SVN_ERR(svn_cl__xml_print_header("properties", scratch_pool));
          pl_receiver = proplist_receiver_xml;
        }
      else
        {
          pl_receiver = proplist_receiver;
        }

      if (opt_state->depth == svn_depth_unknown)
        opt_state->depth = svn_depth_empty;

      iterpool = svn_pool_create(scratch_pool);
      for (i = 0; i < targets->nelts; i++)
        {
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          proplist_baton_t pl_baton;
          const char *truepath;
          svn_opt_revision_t peg_revision;
          svn_boolean_t success;

          svn_pool_clear(iterpool);
          SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

          pl_baton.is_url = svn_path_is_url(target);
          pl_baton.opt_state = opt_state;

          /* Check for a peg revision. */
          SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                     iterpool));

          SVN_ERR(svn_cl__try(
                   svn_client_proplist3(truepath, &peg_revision,
                                        &(opt_state->start_revision),
                                        opt_state->depth,
                                        opt_state->changelists,
                                        pl_receiver, &pl_baton,
                                        ctx, iterpool),
                   &success, opt_state->quiet,
                   SVN_ERR_UNVERSIONED_RESOURCE,
                   SVN_ERR_ENTRY_NOT_FOUND,
                   SVN_NO_ERROR));

          if (!success)
            had_errors = TRUE;
        }
      svn_pool_destroy(iterpool);

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_footer("properties", scratch_pool));

      /* Error out *after* we closed the XML element */
      if (had_errors)
        return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
                                _("Could not display info for all targets "
                                  "because some targets don't exist"));
    }

  return SVN_NO_ERROR;
}
/* This implements the svn_client_list_func_t API, printing a single dirent
   in XML format. */
static svn_error_t *
print_dirent_xml(void *baton,
                 const char *path,
                 const svn_dirent_t *dirent,
                 const svn_lock_t *lock,
                 const char *abs_path,
                 apr_pool_t *pool)
{
  struct print_baton *pb = baton;
  const char *entryname;
  svn_stringbuf_t *sb;

  if (strcmp(path, "") == 0)
    {
      if (dirent->kind == svn_node_file)
        entryname = svn_dirent_basename(abs_path, pool);
      else if (pb->verbose)
        entryname = ".";
      else
        /* Don't bother to list if no useful information will be shown. */
        return SVN_NO_ERROR;
    }
  else
    entryname = path;

  if (pb->ctx->cancel_func)
    SVN_ERR(pb->ctx->cancel_func(pb->ctx->cancel_baton));

  sb = svn_stringbuf_create("", pool);

  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "kind", svn_cl__node_kind_str_xml(dirent->kind),
                        NULL);

  svn_cl__xml_tagged_cdata(&sb, pool, "name", entryname);

  if (dirent->kind == svn_node_file)
    {
      svn_cl__xml_tagged_cdata
        (&sb, pool, "size",
         apr_psprintf(pool, "%" SVN_FILESIZE_T_FMT, dirent->size));
    }

  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "commit",
                        "revision",
                        apr_psprintf(pool, "%ld", dirent->created_rev),
                        NULL);
  svn_cl__xml_tagged_cdata(&sb, pool, "author", dirent->last_author);
  if (dirent->time)
    svn_cl__xml_tagged_cdata(&sb, pool, "date",
                             svn_time_to_cstring(dirent->time, pool));
  svn_xml_make_close_tag(&sb, pool, "commit");

  if (lock)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);
      svn_cl__xml_tagged_cdata(&sb, pool, "token", lock->token);
      svn_cl__xml_tagged_cdata(&sb, pool, "owner", lock->owner);
      svn_cl__xml_tagged_cdata(&sb, pool, "comment", lock->comment);
      svn_cl__xml_tagged_cdata(&sb, pool, "created",
                               svn_time_to_cstring(lock->creation_date,
                                                   pool));
      if (lock->expiration_date != 0)
        svn_cl__xml_tagged_cdata(&sb, pool, "expires",
                                 svn_time_to_cstring
                                 (lock->expiration_date, pool));
      svn_xml_make_close_tag(&sb, pool, "lock");
    }

  svn_xml_make_close_tag(&sb, pool, "entry");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
/* This implements the svn_client_blame_receiver3_t interface, printing
   XML to stdout. */
static svn_error_t *
blame_receiver_xml(void *baton,
                   svn_revnum_t start_revnum,
                   svn_revnum_t end_revnum,
                   apr_int64_t line_no,
                   svn_revnum_t revision,
                   apr_hash_t *rev_props,
                   svn_revnum_t merged_revision,
                   apr_hash_t *merged_rev_props,
                   const char *merged_path,
                   const char *line,
                   svn_boolean_t local_change,
                   apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state =
    ((blame_baton_t *) baton)->opt_state;
  svn_stringbuf_t *sb = ((blame_baton_t *) baton)->sbuf;

  /* "<entry ...>" */
  /* line_no is 0-based, but the rest of the world is probably Pascal
     programmers, so we make them happy and output 1-based line numbers. */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "line-number",
                        apr_psprintf(pool, "%" APR_INT64_T_FMT,
                                     line_no + 1),
                        NULL);

  if (SVN_IS_VALID_REVNUM(revision))
    svn_cl__print_xml_commit(&sb, revision,
                             svn_prop_get_value(rev_props,
                                                SVN_PROP_REVISION_AUTHOR),
                             svn_prop_get_value(rev_props,
                                                SVN_PROP_REVISION_DATE),
                             pool);

  if (opt_state->use_merge_history && SVN_IS_VALID_REVNUM(merged_revision))
    {
      /* "<merged>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "merged",
                            "path", merged_path, NULL);

      svn_cl__print_xml_commit(&sb, merged_revision,
                             svn_prop_get_value(merged_rev_props,
                                                SVN_PROP_REVISION_AUTHOR),
                             svn_prop_get_value(merged_rev_props,
                                                SVN_PROP_REVISION_DATE),
                             pool);

      /* "</merged>" */
      svn_xml_make_close_tag(&sb, pool, "merged");

    }

  /* "</entry>" */
  svn_xml_make_close_tag(&sb, pool, "entry");

  SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
  svn_stringbuf_setempty(sb);

  return SVN_NO_ERROR;
}
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__blame(apr_getopt_t *os,
              void *baton,
              apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_pool_t *subpool;
  apr_array_header_t *targets;
  blame_baton_t bl;
  int i;
  svn_boolean_t end_revision_unspecified = FALSE;
  svn_diff_file_options_t *diff_options = svn_diff_file_options_create(pool);
  svn_boolean_t seen_nonexistent_target = FALSE;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));

  /* Blame needs a file on which to operate. */
  if (! targets->nelts)
    return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);

  if (opt_state->end_revision.kind == svn_opt_revision_unspecified)
    {
      if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
        {
          /* In the case that -rX was specified, we actually want to set the
             range to be -r1:X. */

          opt_state->end_revision = opt_state->start_revision;
          opt_state->start_revision.kind = svn_opt_revision_number;
          opt_state->start_revision.value.number = 1;
        }
      else
        end_revision_unspecified = TRUE;
    }

  if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
    {
      opt_state->start_revision.kind = svn_opt_revision_number;
      opt_state->start_revision.value.number = 1;
    }

  /* The final conclusion from issue #2431 is that blame info
     is client output (unlike 'svn cat' which plainly cats the file),
     so the EOL style should be the platform local one.
  */
  if (! opt_state->xml)
    SVN_ERR(svn_stream_for_stdout(&bl.out, pool));
  else
    bl.sbuf = svn_stringbuf_create("", pool);

  bl.opt_state = opt_state;

  subpool = svn_pool_create(pool);

  if (opt_state->extensions)
    {
      apr_array_header_t *opts;
      opts = svn_cstring_split(opt_state->extensions, " \t\n\r", TRUE, pool);
      SVN_ERR(svn_diff_file_options_parse(diff_options, opts, pool));
    }

  if (opt_state->xml)
    {
      if (opt_state->verbose)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'verbose' option invalid in XML mode"));

      /* If output is not incremental, output the XML header and wrap
         everything in a top-level element.  This makes the output in
         its entirety a well-formed XML document. */
      if (! opt_state->incremental)
        SVN_ERR(svn_cl__xml_print_header("blame", pool));
    }
  else
    {
      if (opt_state->incremental)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'incremental' option only valid in XML "
                                  "mode"));
    }

  for (i = 0; i < targets->nelts; i++)
    {
      svn_error_t *err;
      const char *target = APR_ARRAY_IDX(targets, i, const char *);
      const char *truepath;
      svn_opt_revision_t peg_revision;
      svn_client_blame_receiver3_t receiver;

      svn_pool_clear(subpool);
      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

      /* Check for a peg revision. */
      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                 subpool));

      if (end_revision_unspecified)
        {
          if (peg_revision.kind != svn_opt_revision_unspecified)
            opt_state->end_revision = peg_revision;
          else if (svn_path_is_url(target))
            opt_state->end_revision.kind = svn_opt_revision_head;
          else
            opt_state->end_revision.kind = svn_opt_revision_working;
        }

      if (opt_state->xml)
        {
          /* "<target ...>" */
          /* We don't output this tag immediately, which avoids creating
             a target element if this path is skipped. */
          const char *outpath = truepath;
          if (! svn_path_is_url(target))
            outpath = svn_dirent_local_style(truepath, subpool);
          svn_xml_make_open_tag(&bl.sbuf, pool, svn_xml_normal, "target",
                                "path", outpath, NULL);

          receiver = blame_receiver_xml;
        }
      else
        receiver = blame_receiver;

      err = svn_client_blame5(truepath,
                              &peg_revision,
                              &opt_state->start_revision,
                              &opt_state->end_revision,
                              diff_options,
                              opt_state->force,
                              opt_state->use_merge_history,
                              receiver,
                              &bl,
                              ctx,
                              subpool);

      if (err)
        {
          if (err->apr_err == SVN_ERR_CLIENT_IS_BINARY_FILE)
            {
              svn_error_clear(err);
              SVN_ERR(svn_cmdline_fprintf(stderr, subpool,
                                          _("Skipping binary file: '%s'\n"),
                                          target));
            }
          else if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
                   err->apr_err == SVN_ERR_FS_NOT_FILE ||
                   err->apr_err == SVN_ERR_FS_NOT_FOUND)
            {
              svn_handle_warning2(stderr, err, "svn: ");
              svn_error_clear(err);
              err = NULL;
              seen_nonexistent_target = TRUE;
            }
          else
            {
              return svn_error_trace(err);
            }
        }
      else if (opt_state->xml)
        {
          /* "</target>" */
          svn_xml_make_close_tag(&(bl.sbuf), pool, "target");
          SVN_ERR(svn_cl__error_checked_fputs(bl.sbuf->data, stdout));
        }

      if (opt_state->xml)
        svn_stringbuf_setempty(bl.sbuf);
    }
  svn_pool_destroy(subpool);
  if (opt_state->xml && ! opt_state->incremental)
    SVN_ERR(svn_cl__xml_print_footer("blame", pool));

  if (seen_nonexistent_target)
    return svn_error_create(
      SVN_ERR_ILLEGAL_TARGET, NULL,
      _("Could not perform blame on all targets because some "
        "targets don't exist"));
  else
    return SVN_NO_ERROR;
}
Example #13
0
svn_error_t *
svn_cl__print_status_xml(const char *cwd_abspath,
                         const char *path,
                         const svn_client_status_t *status,
                         svn_client_ctx_t *ctx,
                         apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create_empty(pool);
  apr_hash_t *att_hash;
  const char *local_abspath = status->local_abspath;
  svn_boolean_t tree_conflicted = FALSE;

  if (status->node_status == svn_wc_status_none
      && status->repos_node_status == svn_wc_status_none)
    return SVN_NO_ERROR;

  if (status->conflicted)
    SVN_ERR(svn_wc_conflicted_p3(NULL, NULL, &tree_conflicted,
                                 ctx->wc_ctx, local_abspath, pool));

  path = make_relpath(cwd_abspath, path, pool, pool);

  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_dirent_local_style(path, pool), NULL);

  att_hash = apr_hash_make(pool);
  svn_hash_sets(att_hash, "item",
                generate_status_desc(combined_status(status)));

  svn_hash_sets(att_hash, "props",
                generate_status_desc(
                   (status->node_status != svn_wc_status_deleted)
                   ? status->prop_status
                   : svn_wc_status_none));
  if (status->wc_is_locked)
    svn_hash_sets(att_hash, "wc-locked", "true");
  if (status->copied)
    svn_hash_sets(att_hash, "copied", "true");
  if (status->switched)
    svn_hash_sets(att_hash, "switched", "true");
  if (status->file_external)
    svn_hash_sets(att_hash, "file-external", "true");
  if (status->versioned && ! status->copied)
    svn_hash_sets(att_hash, "revision",
                  apr_psprintf(pool, "%ld", status->revision));
  if (tree_conflicted)
    svn_hash_sets(att_hash, "tree-conflicted", "true");
  if (status->moved_from_abspath || status->moved_to_abspath)
    {
      const char *relpath;

      if (status->moved_from_abspath)
        {
          relpath = make_relpath(cwd_abspath, status->moved_from_abspath,
                                 pool, pool);
          relpath = svn_dirent_local_style(relpath, pool);
          svn_hash_sets(att_hash, "moved-from", relpath);
        }
      if (status->moved_to_abspath)
        {
          relpath = make_relpath(cwd_abspath, status->moved_to_abspath,
                                 pool, pool);
          relpath = svn_dirent_local_style(relpath, pool);
          svn_hash_sets(att_hash, "moved-to", relpath);
        }
    }
  svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status",
                             att_hash);

  if (SVN_IS_VALID_REVNUM(status->changed_rev))
    {
      svn_cl__print_xml_commit(&sb, status->changed_rev,
                               status->changed_author,
                               svn_time_to_cstring(status->changed_date,
                                                   pool),
                               pool);
    }

  if (status->lock)
    svn_cl__print_xml_lock(&sb, status->lock, pool);

  svn_xml_make_close_tag(&sb, pool, "wc-status");

  if (status->repos_node_status != svn_wc_status_none
      || status->repos_lock)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repos-status",
                            "item",
                            generate_status_desc(combined_repos_status(status)),
                            "props",
                            generate_status_desc(status->repos_prop_status),
                            NULL);
      if (status->repos_lock)
        svn_cl__print_xml_lock(&sb, status->repos_lock, pool);

      svn_xml_make_close_tag(&sb, pool, "repos-status");
    }

  svn_xml_make_close_tag(&sb, pool, "entry");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #14
0
/* A callback of type svn_client_info_receiver2_t.
   Prints svn info in xml mode to standard out */
static svn_error_t *
print_info_xml(void *baton,
               const char *target,
               const svn_client_info2_t *info,
               apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  const char *rev_str;
  const char *path_prefix = baton;

  if (SVN_IS_VALID_REVNUM(info->rev))
    rev_str = apr_psprintf(pool, "%ld", info->rev);
  else
    rev_str = apr_pstrdup(pool, _("Resource is not under version control."));

  /* "<entry ...>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_cl__local_style_skip_ancestor(
                                  path_prefix, target, pool),
                        "kind", svn_cl__node_kind_str_xml(info->kind),
                        "revision", rev_str,
                        NULL);

  svn_cl__xml_tagged_cdata(&sb, pool, "url", info->URL);

  if (info->repos_root_URL || info->repos_UUID)
    {
      /* "<repository>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository", NULL);

      /* "<root> xx </root>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "root", info->repos_root_URL);

      /* "<uuid> xx </uuid>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "uuid", info->repos_UUID);

      /* "</repository>" */
      svn_xml_make_close_tag(&sb, pool, "repository");
    }

  if (info->wc_info)
    {
      /* "<wc-info>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);

      /* "<wcroot-abspath> xx </wcroot-abspath>" */
      if (info->wc_info->wcroot_abspath)
        svn_cl__xml_tagged_cdata(&sb, pool, "wcroot-abspath",
                                 info->wc_info->wcroot_abspath);

      /* "<schedule> xx </schedule>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "schedule",
                               schedule_str(info->wc_info->schedule));

      /* "<depth> xx </depth>" */
      {
        svn_depth_t depth = info->wc_info->depth;

        /* In the entries world info just passed depth infinity for files */
        if (depth == svn_depth_unknown && info->kind == svn_node_file)
          depth = svn_depth_infinity;

        svn_cl__xml_tagged_cdata(&sb, pool, "depth", svn_depth_to_word(depth));
      }

      /* "<copy-from-url> xx </copy-from-url>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-url",
                               info->wc_info->copyfrom_url);

      /* "<copy-from-rev> xx </copy-from-rev>" */
      if (SVN_IS_VALID_REVNUM(info->wc_info->copyfrom_rev))
        svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-rev",
                                 apr_psprintf(pool, "%ld",
                                              info->wc_info->copyfrom_rev));

      /* "<text-updated> xx </text-updated>" */
      if (info->wc_info->recorded_time)
        svn_cl__xml_tagged_cdata(&sb, pool, "text-updated",
                                 svn_time_to_cstring(
                                          info->wc_info->recorded_time,
                                          pool));

      /* "<checksum> xx </checksum>" */
      /* ### Print the checksum kind. */
      svn_cl__xml_tagged_cdata(&sb, pool, "checksum",
                               svn_checksum_to_cstring(info->wc_info->checksum,
                                                       pool));

      if (info->wc_info->changelist)
        /* "<changelist> xx </changelist>" */
        svn_cl__xml_tagged_cdata(&sb, pool, "changelist",
                                 info->wc_info->changelist);

      /* "</wc-info>" */
      svn_xml_make_close_tag(&sb, pool, "wc-info");
    }

  if (info->last_changed_author
      || SVN_IS_VALID_REVNUM(info->last_changed_rev)
      || info->last_changed_date)
    {
      svn_cl__print_xml_commit(&sb, info->last_changed_rev,
                               info->last_changed_author,
                               svn_time_to_cstring(info->last_changed_date,
                                                   pool),
                               pool);
    }

  if (info->wc_info && info->wc_info->conflicts)
    {
      int i;

      for (i = 0; i < info->wc_info->conflicts->nelts; i++)
        {
          const svn_wc_conflict_description2_t *conflict =
                      APR_ARRAY_IDX(info->wc_info->conflicts, i,
                                    const svn_wc_conflict_description2_t *);

          switch (conflict->kind)
            {
              case svn_wc_conflict_kind_text:
                /* "<conflict>" */
                svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "conflict",
                                      NULL);

                /* "<prev-base-file> xx </prev-base-file>" */
                svn_cl__xml_tagged_cdata(&sb, pool, "prev-base-file",
                                         conflict->base_abspath);

                /* "<prev-wc-file> xx </prev-wc-file>" */
                svn_cl__xml_tagged_cdata(&sb, pool, "prev-wc-file",
                                         conflict->my_abspath);

                /* "<cur-base-file> xx </cur-base-file>" */
                svn_cl__xml_tagged_cdata(&sb, pool, "cur-base-file",
                                         conflict->their_abspath);

                /* "</conflict>" */
                svn_xml_make_close_tag(&sb, pool, "conflict");
              break;

              case svn_wc_conflict_kind_property:
                /* "<conflict>" */
                svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "conflict",
                                      NULL);

                /* "<prop-file> xx </prop-file>" */
                svn_cl__xml_tagged_cdata(&sb, pool, "prop-file",
                                         conflict->their_abspath);

                /* "</conflict>" */
                svn_xml_make_close_tag(&sb, pool, "conflict");
              break;

              case svn_wc_conflict_kind_tree:
                SVN_ERR(svn_cl__append_tree_conflict_info_xml(sb, conflict,
                                                              pool));
              break;
            }
        }
    }
Example #15
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__status(apr_getopt_t *os,
               void *baton,
               apr_pool_t *scratch_pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_array_header_t *targets;
  apr_pool_t *iterpool;
  apr_hash_t *master_cl_hash = apr_hash_make(scratch_pool);
  int i;
  svn_opt_revision_t rev;
  struct status_baton sb;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE,
                                                      scratch_pool));

  /* Add "." if user passed 0 arguments */
  svn_opt_push_implicit_dot_target(targets, scratch_pool);

  SVN_ERR(svn_cl__check_targets_are_local_paths(targets));

  /* We want our -u statuses to be against HEAD by default. */
  if (opt_state->start_revision.kind == svn_opt_revision_unspecified)
    rev.kind = svn_opt_revision_head;
  else if (! opt_state->update)
    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                        _("--revision (-r) option valid only with "
                          "--show-updates (-u) option"));
  else
    rev = opt_state->start_revision;

  sb.had_print_error = FALSE;

  if (opt_state->xml)
    {
      /* If output is not incremental, output the XML header and wrap
         everything in a top-level element. This makes the output in
         its entirety a well-formed XML document. */
      if (! opt_state->incremental)
        SVN_ERR(svn_cl__xml_print_header("status", scratch_pool));
    }
  else
    {
      if (opt_state->incremental)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'incremental' option only valid in XML "
                                  "mode"));
    }

  sb.suppress_externals_placeholders = (opt_state->quiet
                                        && (! opt_state->verbose));
  sb.detailed = (opt_state->verbose || opt_state->update);
  sb.show_last_committed = opt_state->verbose;
  sb.skip_unrecognized = opt_state->quiet;
  sb.repos_locks = opt_state->update;
  sb.xml_mode = opt_state->xml;
  sb.cached_changelists = master_cl_hash;
  sb.cl_pool = scratch_pool;
  sb.text_conflicts = 0;
  sb.prop_conflicts = 0;
  sb.tree_conflicts = 0;
  sb.ctx = ctx;

  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));

  iterpool = svn_pool_create(scratch_pool);
  for (i = 0; i < targets->nelts; i++)
    {
      const char *target = APR_ARRAY_IDX(targets, i, const char *);
      svn_revnum_t repos_rev = SVN_INVALID_REVNUM;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_dirent_get_absolute(&(sb.target_abspath), target,
                                      scratch_pool));
      sb.target_path = target;

      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

      if (opt_state->xml)
        SVN_ERR(print_start_target_xml(svn_dirent_local_style(target, iterpool),
                                       iterpool));

      /* Retrieve a hash of status structures with the information
         requested by the user. */
      SVN_ERR(svn_cl__try(svn_client_status6(&repos_rev, ctx, target, &rev,
                                             opt_state->depth,
                                             opt_state->verbose,
                                             opt_state->update,
                                             TRUE /* check_working_copy */,
                                             opt_state->no_ignore,
                                             opt_state->ignore_externals,
                                             FALSE /* depth_as_sticky */,
                                             opt_state->changelists,
                                             print_status, &sb,
                                             iterpool),
                          NULL, opt_state->quiet,
                          /* not versioned: */
                          SVN_ERR_WC_NOT_WORKING_COPY,
                          SVN_ERR_WC_PATH_NOT_FOUND,
                          0));

      if (opt_state->xml)
        SVN_ERR(print_finish_target_xml(repos_rev, iterpool));
    }

  /* If any paths were cached because they were associated with
     changelists, we can now display them as grouped changelists. */
  if (apr_hash_count(master_cl_hash) > 0)
    {
      apr_hash_index_t *hi;
      svn_stringbuf_t *buf;

      if (opt_state->xml)
        buf = svn_stringbuf_create_empty(scratch_pool);

      for (hi = apr_hash_first(scratch_pool, master_cl_hash); hi;
           hi = apr_hash_next(hi))
        {
          const char *changelist_name = apr_hash_this_key(hi);
          apr_array_header_t *path_array = apr_hash_this_val(hi);
          int j;

          /* ### TODO: For non-XML output, we shouldn't print the
             ### leading \n on the first changelist if there were no
             ### non-changelist entries. */
          if (opt_state->xml)
            {
              svn_stringbuf_setempty(buf);
              svn_xml_make_open_tag(&buf, scratch_pool, svn_xml_normal,
                                    "changelist", "name", changelist_name,
                                    SVN_VA_NULL);
              SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
          else
            SVN_ERR(svn_cmdline_printf(scratch_pool,
                                       _("\n--- Changelist '%s':\n"),
                                       changelist_name));

          for (j = 0; j < path_array->nelts; j++)
            {
              struct status_cache *scache =
                APR_ARRAY_IDX(path_array, j, struct status_cache *);
              sb.target_abspath = scache->target_abspath;
              sb.target_path = scache->target_path;
              SVN_ERR(print_status_normal_or_xml(&sb, scache->path,
                                                 scache->status, scratch_pool));
            }

          if (opt_state->xml)
            {
              svn_stringbuf_setempty(buf);
              svn_xml_make_close_tag(&buf, scratch_pool, "changelist");
              SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
        }
    }
Example #16
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propget(apr_getopt_t *os,
                void *baton,
                apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  const char *pname, *pname_utf8;
  apr_array_header_t *args, *targets;
  svn_stream_t *out;

  if (opt_state->verbose && (opt_state->revprop || opt_state->strict
                             || opt_state->xml))
    return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                            _("--verbose cannot be used with --revprop or "
                              "--strict or --xml"));

  /* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version
     thereof) */
  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
  pname = APR_ARRAY_IDX(args, 0, const char *);
  SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool));
  if (! svn_prop_name_is_valid(pname_utf8))
    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                             _("'%s' is not a valid Subversion property name"),
                             pname_utf8);

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));

  /* Add "." if user passed 0 file arguments */
  svn_opt_push_implicit_dot_target(targets, pool);

  /* Open a stream to stdout. */
  SVN_ERR(svn_stream_for_stdout(&out, pool));

  if (opt_state->revprop)  /* operate on a revprop */
    {
      svn_revnum_t rev;
      const char *URL;
      svn_string_t *propval;

      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
                                      &URL, ctx, pool));

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_get(pname_utf8, &propval,
                                     URL, &(opt_state->start_revision),
                                     &rev, ctx, pool));

      if (propval != NULL)
        {
          if (opt_state->xml)
            {
              svn_stringbuf_t *sb = NULL;
              char *revstr = apr_psprintf(pool, "%ld", rev);

              SVN_ERR(svn_cl__xml_print_header("properties", pool));

              svn_xml_make_open_tag(&sb, pool, svn_xml_normal,
                                    "revprops",
                                    "rev", revstr, NULL);

              svn_cmdline__print_xml_prop(&sb, pname_utf8, propval, pool);

              svn_xml_make_close_tag(&sb, pool, "revprops");

              SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
              SVN_ERR(svn_cl__xml_print_footer("properties", pool));
            }
          else
            {
              svn_string_t *printable_val = propval;

              /* If this is a special Subversion property, it is stored as
                 UTF8 and LF, so convert to the native locale and eol-style. */

              if (svn_prop_needs_translation(pname_utf8))
                SVN_ERR(svn_subst_detranslate_string(&printable_val, propval,
                                                     TRUE, pool));

              SVN_ERR(stream_write(out, printable_val->data,
                                   printable_val->len));
              if (! opt_state->strict)
                SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
            }
        }
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      apr_pool_t *subpool = svn_pool_create(pool);
      int i;

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_header("properties", subpool));

      if (opt_state->depth == svn_depth_unknown)
        opt_state->depth = svn_depth_empty;

      /* Strict mode only makes sense for a single target.  So make
         sure we have only a single target, and that we're not being
         asked to recurse on that target. */
      if (opt_state->strict
          && ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)))
        return svn_error_create
          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
           _("Strict output of property values only available for single-"
             "target, non-recursive propget operations"));

      for (i = 0; i < targets->nelts; i++)
        {
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          apr_hash_t *props;
          svn_boolean_t print_filenames;
          svn_boolean_t omit_newline;
          svn_boolean_t like_proplist;
          const char *truepath;
          svn_opt_revision_t peg_revision;

          svn_pool_clear(subpool);
          SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

          /* Check for a peg revision. */
          SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                     subpool));

          if (!svn_path_is_url(truepath))
            SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));

          SVN_ERR(svn_client_propget4(&props, pname_utf8, truepath,
                                      &peg_revision,
                                      &(opt_state->start_revision),
                                      NULL, opt_state->depth,
                                      opt_state->changelists, ctx, subpool,
                                      subpool));

          /* Any time there is more than one thing to print, or where
             the path associated with a printed thing is not obvious,
             we'll print filenames.  That is, unless we've been told
             not to do so with the --strict option. */
          print_filenames = ((opt_state->depth > svn_depth_empty
                              || targets->nelts > 1
                              || apr_hash_count(props) > 1
                              || opt_state->verbose)
                             && (! opt_state->strict));
          omit_newline = opt_state->strict;
          like_proplist = opt_state->verbose && !opt_state->strict;

          if (opt_state->xml)
            SVN_ERR(print_properties_xml(pname_utf8, props, subpool));
          else
            SVN_ERR(print_properties(out, svn_path_is_url(target), pname_utf8,
                                     props, print_filenames, omit_newline,
                                     like_proplist, subpool));
        }

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_footer("properties", subpool));

      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__list(apr_getopt_t *os,
             void *baton,
             apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_array_header_t *targets;
  int i;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_uint32_t dirent_fields;
  struct print_baton pb;
  svn_boolean_t seen_nonexistent_target = FALSE;
  svn_error_t *err;

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));

  /* Add "." if user passed 0 arguments */
  svn_opt_push_implicit_dot_target(targets, pool);

  if (opt_state->xml)
    {
      /* The XML output contains all the information, so "--verbose"
         does not apply. */
      if (opt_state->verbose)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'verbose' option invalid in XML mode"));

      /* If output is not incremental, output the XML header and wrap
         everything in a top-level element. This makes the output in
         its entirety a well-formed XML document. */
      if (! opt_state->incremental)
        SVN_ERR(svn_cl__xml_print_header("lists", pool));
    }
  else
    {
      if (opt_state->incremental)
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'incremental' option only valid in XML "
                                  "mode"));
    }

  if (opt_state->verbose || opt_state->xml)
    dirent_fields = SVN_DIRENT_ALL;
  else
    dirent_fields = SVN_DIRENT_KIND; /* the only thing we actually need... */

  pb.ctx = ctx;
  pb.verbose = opt_state->verbose;

  if (opt_state->depth == svn_depth_unknown)
    opt_state->depth = svn_depth_immediates;

  /* For each target, try to list it. */
  for (i = 0; i < targets->nelts; i++)
    {
      const char *target = APR_ARRAY_IDX(targets, i, const char *);
      const char *truepath;
      svn_opt_revision_t peg_revision;

      svn_pool_clear(subpool);

      SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

      /* Get peg revisions. */
      SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                 subpool));

      if (opt_state->xml)
        {
          svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
          svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "list",
                                "path", truepath[0] == '\0' ? "." : truepath,
                                NULL);
          SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
        }

      err = svn_client_list2(truepath, &peg_revision,
                             &(opt_state->start_revision),
                             opt_state->depth,
                             dirent_fields,
                             (opt_state->xml || opt_state->verbose),
                             opt_state->xml ? print_dirent_xml : print_dirent,
                             &pb, ctx, subpool);

      if (err)
        {
          /* If one of the targets is a non-existent URL or wc-entry,
             don't bail out.  Just warn and move on to the next target. */
          if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND ||
              err->apr_err == SVN_ERR_FS_NOT_FOUND)
              svn_handle_warning2(stderr, err, "svn: ");
          else
              return svn_error_trace(err);

          svn_error_clear(err);
          err = NULL;
          seen_nonexistent_target = TRUE;
        }

      if (opt_state->xml)
        {
          svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
          svn_xml_make_close_tag(&sb, pool, "list");
          SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
        }
    }

  svn_pool_destroy(subpool);

  if (opt_state->xml && ! opt_state->incremental)
    SVN_ERR(svn_cl__xml_print_footer("lists", pool));

  if (seen_nonexistent_target)
    return svn_error_create(
      SVN_ERR_ILLEGAL_TARGET, NULL,
      _("Could not list all targets because some targets don't exist"));
  else
    return SVN_NO_ERROR;
}
Example #18
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__status(apr_getopt_t *os,
               void *baton,
               apr_pool_t *pool)
{
    svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
    svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
    apr_array_header_t *targets;
    apr_pool_t *subpool;
    apr_hash_t *master_cl_hash = apr_hash_make(pool);
    int i;
    svn_opt_revision_t rev;
    struct status_baton sb;

    SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
            opt_state->targets,
            ctx, pool));

    /* Add "." if user passed 0 arguments */
    svn_opt_push_implicit_dot_target(targets, pool);

    /* We want our -u statuses to be against HEAD. */
    rev.kind = svn_opt_revision_head;

    /* The notification callback, leave the notifier as NULL in XML mode */
    if (! opt_state->xml)
        svn_cl__get_notifier(&ctx->notify_func2, &ctx->notify_baton2, FALSE,
                             FALSE, FALSE, pool);

    subpool = svn_pool_create(pool);

    sb.had_print_error = FALSE;

    if (opt_state->xml)
    {
        /* If output is not incremental, output the XML header and wrap
           everything in a top-level element. This makes the output in
           its entirety a well-formed XML document. */
        if (! opt_state->incremental)
            SVN_ERR(svn_cl__xml_print_header("status", pool));
    }
    else
    {
        if (opt_state->incremental)
            return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                    _("'incremental' option only valid in XML "
                                      "mode"));
    }

    sb.detailed = (opt_state->verbose || opt_state->update);
    sb.show_last_committed = opt_state->verbose;
    sb.skip_unrecognized = opt_state->quiet;
    sb.repos_locks = opt_state->update;
    sb.xml_mode = opt_state->xml;
    sb.cached_changelists = master_cl_hash;
    sb.cl_pool = pool;

    SVN_ERR(svn_opt__eat_peg_revisions(&targets, targets, pool));

    for (i = 0; i < targets->nelts; i++)
    {
        const char *target = APR_ARRAY_IDX(targets, i, const char *);
        svn_revnum_t repos_rev = SVN_INVALID_REVNUM;

        svn_pool_clear(subpool);

        SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

        if (opt_state->xml)
            SVN_ERR(print_start_target_xml(svn_path_local_style(target, subpool),
                                           subpool));

        /* Retrieve a hash of status structures with the information
           requested by the user. */
        SVN_ERR(svn_cl__try(svn_client_status4(&repos_rev, target, &rev,
                                               print_status, &sb,
                                               opt_state->depth,
                                               opt_state->verbose,
                                               opt_state->update,
                                               opt_state->no_ignore,
                                               opt_state->ignore_externals,
                                               opt_state->changelists,
                                               ctx, subpool),
                            NULL, opt_state->quiet,
                            /* not versioned: */
                            SVN_ERR_WC_NOT_DIRECTORY,
                            SVN_NO_ERROR));

        if (opt_state->xml)
            SVN_ERR(print_finish_target_xml(repos_rev, subpool));
    }

    /* If any paths were cached because they were associatied with
       changelists, we can now display them as grouped changelists. */
    if (apr_hash_count(master_cl_hash) > 0)
    {
        apr_hash_index_t *hi;
        svn_stringbuf_t *buf;

        if (opt_state->xml)
            buf = svn_stringbuf_create("", pool);

        for (hi = apr_hash_first(pool, master_cl_hash); hi;
                hi = apr_hash_next(hi))
        {
            const char *changelist_name;
            apr_array_header_t *path_array;
            const void *key;
            void *val;
            int j;

            apr_hash_this(hi, &key, NULL, &val);
            changelist_name = key;
            path_array = val;

            /* ### TODO: For non-XML output, we shouldn't print the
               ### leading \n on the first changelist if there were no
               ### non-changelist entries. */
            if (opt_state->xml)
            {
                svn_stringbuf_set(buf, "");
                svn_xml_make_open_tag(&buf, pool, svn_xml_normal, "changelist",
                                      "name", changelist_name, NULL);
                SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
            else
                SVN_ERR(svn_cmdline_printf(pool, _("\n--- Changelist '%s':\n"),
                                           changelist_name));

            for (j = 0; j < path_array->nelts; j++)
            {
                struct status_cache *scache =
                    APR_ARRAY_IDX(path_array, j, struct status_cache *);
                SVN_ERR(print_status_normal_or_xml(&sb, scache->path,
                                                   scache->status, pool));
            }

            if (opt_state->xml)
            {
                svn_stringbuf_set(buf, "");
                svn_xml_make_close_tag(&buf, pool, "changelist");
                SVN_ERR(svn_cl__error_checked_fputs(buf->data, stdout));
            }
        }
    }
Example #19
0
/* This implements `svn_log_entry_receiver_t', printing the logs in XML.
 *
 * BATON is of type `struct log_receiver_baton'.
 *
 * Here is an example of the output; note that the "<log>" and
 * "</log>" tags are not emitted by this function:
 *
 * $ svn log --xml -r 1648:1649
 * <log>
 * <logentry
 *    revision="1648">
 * <author>david</author>
 * <date>2002-04-06T16:34:51.428043Z</date>
 * <msg> * packages/rpm/subversion.spec : Now requires apache 2.0.36.
 * </msg>
 * </logentry>
 * <logentry
 *    revision="1649">
 * <author>cmpilato</author>
 * <date>2002-04-06T17:01:28.185136Z</date>
 * <msg>Fix error handling when the $EDITOR is needed but unavailable.  Ah
 * ... now that&apos;s *much* nicer.
 *
 * * subversion/clients/cmdline/util.c
 *   (svn_cl__edit_externally): Clean up the &quot;no external editor&quot;
 *   error message.
 *   (svn_cl__get_log_message): Wrap &quot;no external editor&quot;
 *   errors with helpful hints about the -m and -F options.
 *
 * * subversion/libsvn_client/commit.c
 *   (svn_client_commit): Actually capture and propogate &quot;no external
 *   editor&quot; errors.</msg>
 * </logentry>
 * </log>
 *
 */
static svn_error_t *
log_entry_receiver_xml(void *baton,
                       svn_log_entry_t *log_entry,
                       apr_pool_t *pool)
{
  struct log_receiver_baton *lb = baton;
  /* Collate whole log message into sb before printing. */
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  char *revstr;
  const char *author;
  const char *date;
  const char *message;

  if (lb->cancel_func)
    SVN_ERR(lb->cancel_func(lb->cancel_baton));

  svn_compat_log_revprops_out(&author, &date, &message, log_entry->revprops);

  if (author)
    author = svn_xml_fuzzy_escape(author, pool);
  if (date)
    date = svn_xml_fuzzy_escape(date, pool);
  if (message)
    message = svn_xml_fuzzy_escape(message, pool);

  if (log_entry->revision == 0 && message == NULL)
    return SVN_NO_ERROR;

  if (! SVN_IS_VALID_REVNUM(log_entry->revision))
    {
      svn_xml_make_close_tag(&sb, pool, "logentry");
      SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
      apr_array_pop(lb->merge_stack);

      return SVN_NO_ERROR;
    }

  revstr = apr_psprintf(pool, "%ld", log_entry->revision);
  /* <logentry revision="xxx"> */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "logentry",
                        "revision", revstr, NULL);

  /* <author>xxx</author> */
  svn_cl__xml_tagged_cdata(&sb, pool, "author", author);

  /* Print the full, uncut, date.  This is machine output. */
  /* According to the docs for svn_log_entry_receiver_t, either
     NULL or the empty string represents no date.  Avoid outputting an
     empty date element. */
  if (date && date[0] == '\0')
    date = NULL;
  /* <date>xxx</date> */
  svn_cl__xml_tagged_cdata(&sb, pool, "date", date);

  if (log_entry->changed_paths)
    {
      apr_hash_index_t *hi;
      char *path;

      /* <paths> */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths",
                            NULL);

      for (hi = apr_hash_first(pool, log_entry->changed_paths);
           hi != NULL;
           hi = apr_hash_next(hi))
        {
          void *val;
          char action[2];
          svn_log_changed_path_t *log_item;

          apr_hash_this(hi, (void *) &path, NULL, &val);
          log_item = val;

          action[0] = log_item->action;
          action[1] = '\0';
          if (log_item->copyfrom_path
              && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev))
            {
              /* <path action="X" copyfrom-path="xxx" copyfrom-rev="xxx"> */
              svn_stringbuf_t *escpath = svn_stringbuf_create("", pool);
              svn_xml_escape_attr_cstring(&escpath,
                                          log_item->copyfrom_path, pool);
              revstr = apr_psprintf(pool, "%ld",
                                    log_item->copyfrom_rev);
              svn_xml_make_open_tag(&sb, pool, svn_xml_protect_pcdata, "path",
                                    "action", action,
                                    "copyfrom-path", escpath->data,
                                    "copyfrom-rev", revstr, NULL);
            }
          else
            {
              /* <path action="X"> */
              svn_xml_make_open_tag(&sb, pool, svn_xml_protect_pcdata, "path",
                                    "action", action, NULL);
            }
          /* xxx</path> */
          svn_xml_escape_cdata_cstring(&sb, path, pool);
          svn_xml_make_close_tag(&sb, pool, "path");
        }

      /* </paths> */
      svn_xml_make_close_tag(&sb, pool, "paths");
    }

  if (message != NULL)
    {
      /* <msg>xxx</msg> */
      svn_cl__xml_tagged_cdata(&sb, pool, "msg", message);
    }

  svn_compat_log_revprops_clear(log_entry->revprops);
  if (log_entry->revprops && apr_hash_count(log_entry->revprops) > 0)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "revprops", NULL);
      SVN_ERR(svn_cl__print_xml_prop_hash(&sb, log_entry->revprops,
                                          FALSE, /* name_only */
                                          pool));
      svn_xml_make_close_tag(&sb, pool, "revprops");
    }

  if (log_entry->has_children)
    APR_ARRAY_PUSH(lb->merge_stack, svn_revnum_t) = log_entry->revision;
  else
    svn_xml_make_close_tag(&sb, pool, "logentry");

  SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));

  return SVN_NO_ERROR;
}
Example #20
0
svn_error_t *
svn_cl__print_status_xml(const char *path,
                         svn_wc_status2_t *status,
                         apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  apr_hash_t *att_hash;

  if (status->text_status == svn_wc_status_none
      && status->repos_text_status == svn_wc_status_none)
    return SVN_NO_ERROR;

  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_path_local_style(path, pool), NULL);

  att_hash = apr_hash_make(pool);
  apr_hash_set(att_hash, "item", APR_HASH_KEY_STRING,
               generate_status_desc(status->text_status));
  apr_hash_set(att_hash, "props", APR_HASH_KEY_STRING,
               generate_status_desc(status->prop_status));
  if (status->locked)
    apr_hash_set(att_hash, "wc-locked", APR_HASH_KEY_STRING, "true");
  if (status->copied)
    apr_hash_set(att_hash, "copied", APR_HASH_KEY_STRING, "true");
  if (status->switched)
    apr_hash_set(att_hash, "switched", APR_HASH_KEY_STRING, "true");
  if (status->entry && ! status->entry->copied)
    apr_hash_set(att_hash, "revision", APR_HASH_KEY_STRING,
                 apr_psprintf(pool, "%ld", status->entry->revision));
  svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status",
                             att_hash);

  if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "commit",
                            "revision",
                            apr_psprintf(pool, "%ld",
                                         status->entry->cmt_rev),
                            NULL);

      svn_cl__xml_tagged_cdata(&sb, pool, "author",
                               status->entry->cmt_author);

      if (status->entry->cmt_date)
        svn_cl__xml_tagged_cdata(&sb, pool, "date",
                                 svn_time_to_cstring
                                 (status->entry->cmt_date, pool));

      svn_xml_make_close_tag(&sb, pool, "commit");
    }

  if (status->entry && status->entry->lock_token)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

      svn_cl__xml_tagged_cdata(&sb, pool, "token", status->entry->lock_token);

      /* If lock_owner is NULL, assume WC is corrupt. */
      if (status->entry->lock_owner)
        svn_cl__xml_tagged_cdata(&sb, pool, "owner",
                                 status->entry->lock_owner);
      else
        return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
                                 _("'%s' has lock token, but no lock owner"),
                                 svn_path_local_style(path, pool));

      svn_cl__xml_tagged_cdata(&sb, pool, "comment",
                               status->entry->lock_comment);

      svn_cl__xml_tagged_cdata(&sb, pool, "created",
                               svn_time_to_cstring
                               (status->entry->lock_creation_date, pool));

      svn_xml_make_close_tag(&sb, pool, "lock");
    }

  svn_xml_make_close_tag(&sb, pool, "wc-status");

  if (status->repos_text_status != svn_wc_status_none
      || status->repos_prop_status != svn_wc_status_none
      || status->repos_lock)
    {
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repos-status",
                            "item",
                            generate_status_desc(status->repos_text_status),
                            "props",
                            generate_status_desc(status->repos_prop_status),
                            NULL);
      if (status->repos_lock)
        {
          svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

          svn_cl__xml_tagged_cdata(&sb, pool, "token",
                                   status->repos_lock->token);

          svn_cl__xml_tagged_cdata(&sb, pool, "owner",
                                   status->repos_lock->owner);

          svn_cl__xml_tagged_cdata(&sb, pool, "comment",
                                   status->repos_lock->comment);

          svn_cl__xml_tagged_cdata(&sb, pool, "created",
                                   svn_time_to_cstring
                                   (status->repos_lock->creation_date,
                                    pool));

          if (status->repos_lock->expiration_date != 0)
            {
              svn_cl__xml_tagged_cdata(&sb, pool, "expires",
                                       svn_time_to_cstring
                                       (status->repos_lock->expiration_date,
                                        pool));
            }

          svn_xml_make_close_tag(&sb, pool, "lock");
        }
      svn_xml_make_close_tag(&sb, pool, "repos-status");
    }

  svn_xml_make_close_tag(&sb, pool, "entry");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}
Example #21
0
/* A callback of type svn_info_receiver_t.
   Prints svn info in xml mode to standard out */
static svn_error_t *
print_info_xml(void *baton,
               const char *target,
               const svn_info_t *info,
               apr_pool_t *pool)
{
  svn_stringbuf_t *sb = svn_stringbuf_create("", pool);
  const char *rev_str;

  if (SVN_IS_VALID_REVNUM(info->rev))
    rev_str = apr_psprintf(pool, "%ld", info->rev);
  else
    rev_str = apr_pstrdup(pool, _("Resource is not under version control."));

  /* "<entry ...>" */
  svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "entry",
                        "path", svn_path_local_style(target, pool),
                        "kind", svn_cl__node_kind_str_xml(info->kind),
                        "revision", rev_str,
                        NULL);

  svn_cl__xml_tagged_cdata(&sb, pool, "url", info->URL);

  if (info->repos_root_URL || info->repos_UUID)
    {
      /* "<repository>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "repository", NULL);

      /* "<root> xx </root>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "root", info->repos_root_URL);

      /* "<uuid> xx </uuid>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "uuid", info->repos_UUID);

      /* "</repository>" */
      svn_xml_make_close_tag(&sb, pool, "repository");
    }

  if (info->has_wc_info)
    {
      /* "<wc-info>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "wc-info", NULL);

      /* "<schedule> xx </schedule>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "schedule",
                               schedule_str(info->schedule));

      /* "<depth> xx </depth>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "depth",
                               svn_depth_to_word(info->depth));

      /* "<copy-from-url> xx </copy-from-url>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-url",
                               info->copyfrom_url);

      /* "<copy-from-rev> xx </copy-from-rev>" */
      if (SVN_IS_VALID_REVNUM(info->copyfrom_rev))
        svn_cl__xml_tagged_cdata(&sb, pool, "copy-from-rev",
                                 apr_psprintf(pool, "%ld",
                                              info->copyfrom_rev));

      /* "<text-updated> xx </text-updated>" */
      if (info->text_time)
        svn_cl__xml_tagged_cdata(&sb, pool, "text-updated",
                                 svn_time_to_cstring(info->text_time, pool));

      /* "<checksum> xx </checksum>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "checksum", info->checksum);

      if (info->changelist)
        /* "<changelist> xx </changelist>" */
        svn_cl__xml_tagged_cdata(&sb, pool, "changelist", info->changelist);

      /* "</wc-info>" */
      svn_xml_make_close_tag(&sb, pool, "wc-info");
    }

  if (info->last_changed_author
      || SVN_IS_VALID_REVNUM(info->last_changed_rev)
      || info->last_changed_date)
    {
      svn_cl__print_xml_commit(&sb, info->last_changed_rev,
                               info->last_changed_author,
                               svn_time_to_cstring(info->last_changed_date,
                                                   pool),
                               pool);
    }

  if (info->conflict_old || info->conflict_wrk
      || info->conflict_new || info->prejfile)
    {
      /* "<conflict>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "conflict", NULL);

      /* "<prev-base-file> xx </prev-base-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prev-base-file",
                               info->conflict_old);

      /* "<prev-wc-file> xx </prev-wc-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prev-wc-file",
                               info->conflict_wrk);

      /* "<cur-base-file> xx </cur-base-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "cur-base-file",
                               info->conflict_new);

      /* "<prop-file> xx </prop-file>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "prop-file", info->prejfile);

      /* "</conflict>" */
      svn_xml_make_close_tag(&sb, pool, "conflict");
    }

  if (info->lock)
    {
      /* "<lock>" */
      svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "lock", NULL);

      /* "<token> xx </token>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "token", info->lock->token);

      /* "<owner> xx </owner>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "owner", info->lock->owner);

      /* "<comment ...> xxxx </comment>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "comment", info->lock->comment);

      /* "<created> xx </created>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "created",
                               svn_time_to_cstring
                               (info->lock->creation_date, pool));

      /* "<expires> xx </expires>" */
      svn_cl__xml_tagged_cdata(&sb, pool, "expires",
                               svn_time_to_cstring
                               (info->lock->expiration_date, pool));

      /* "</lock>" */
      svn_xml_make_close_tag(&sb, pool, "lock");
    }

  if (info->tree_conflict)
    SVN_ERR(svn_cl__append_tree_conflict_info_xml(sb, info->tree_conflict,
                                                  pool));

  /* "</entry>" */
  svn_xml_make_close_tag(&sb, pool, "entry");

  return svn_cl__error_checked_fputs(sb->data, stdout);
}