⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 update.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
  /* Else this not a resource walk, so either send props or cache them
     to send later, depending on whether this is a modern report
     response or not. */

  qname = apr_xml_quote_string (b->pool, name, 1);

  /* apr_xml_quote_string doesn't realloc if there is nothing to
     quote, so dup the name, but only if necessary. */
  if (qname == name)
    qname = apr_pstrdup (b->pool, name);


  if (b->uc->send_all)
    {
      if (value)
        {
          const svn_string_t *qval;
          
          if (svn_xml_is_xml_safe(value->data, value->len))
            {
              svn_stringbuf_t *tmp = NULL;
              svn_xml_escape_cdata_string(&tmp, value, pool);
              qval = svn_string_create (tmp->data, pool);
              SVN_ERR( send_xml(b->uc, "<S:set-prop name=\"%s\">", qname) );
            }
          else
            {
              qval = svn_base64_encode_string(value, pool);
              SVN_ERR( send_xml(b->uc, 
                                "<S:set-prop name=\"%s\" encoding=\"base64\">" 
                                DEBUG_CR, qname) );
            }
          
          SVN_ERR( send_xml(b->uc, "%s", qval->data) );
          SVN_ERR( send_xml(b->uc, "</S:set-prop>" DEBUG_CR) );
        }
      else  /* value is null, so this is a prop removal */
        {
          SVN_ERR( send_xml(b->uc, "<S:remove-prop name=\"%s\"/>" DEBUG_CR, 
                            qname) );
        }
    }
  else  /* don't do inline response, just cache prop names for close_helper */
    {
      /* For now, store certain entry props, because we'll need to send
         them later as standard DAV ("D:") props.  ### this should go
         away and we should just tunnel those props on through for the
         client to deal with. */
#define NSLEN (sizeof(SVN_PROP_ENTRY_PREFIX) - 1)
      if (! strncmp(name, SVN_PROP_ENTRY_PREFIX, NSLEN))
        {
          if (! strcmp(name, SVN_PROP_ENTRY_COMMITTED_REV))
            {
              b->committed_rev = value ?
                apr_pstrdup(b->pool, value->data) : NULL;
            }
          else if (! strcmp(name, SVN_PROP_ENTRY_COMMITTED_DATE))
            {
              b->committed_date = value ?
                apr_pstrdup(b->pool, value->data) : NULL;
            }
          else if (! strcmp(name, SVN_PROP_ENTRY_LAST_AUTHOR))
            {
              b->last_author = value ?
                apr_pstrdup(b->pool, value->data) : NULL;
            }
      
          return SVN_NO_ERROR;
        }
#undef NSLEN

      if (value)
        {
          if (! b->changed_props)
            b->changed_props = apr_array_make (b->pool, 1, sizeof (name));
          
          (*((const char **)(apr_array_push (b->changed_props)))) = qname;
        }
      else
        {
          if (! b->removed_props)
            b->removed_props = apr_array_make (b->pool, 1, sizeof (name));
          
          (*((const char **)(apr_array_push (b->removed_props)))) = qname;
        }
    }

  return SVN_NO_ERROR;
}

static svn_error_t * upd_close_directory(void *dir_baton,
                                         apr_pool_t *pool)
{
  return close_helper(TRUE /* is_dir */, dir_baton);
}

static svn_error_t * upd_add_file(const char *path,
                                  void *parent_baton,
                                  const char *copyfrom_path,
                                  svn_revnum_t copyfrom_revision,
                                  apr_pool_t *pool,
                                  void **file_baton)
{
  return add_helper(FALSE /* is_dir */,
                    path, parent_baton, copyfrom_path, copyfrom_revision, pool,
                    file_baton);
}

static svn_error_t * upd_open_file(const char *path,
                                   void *parent_baton,
                                   svn_revnum_t base_revision,
                                   apr_pool_t *pool,
                                   void **file_baton)
{
  return open_helper(FALSE /* is_dir */,
                     path, parent_baton, base_revision, pool, file_baton);
}


/* We have our own window handler and baton as a simple wrapper around
   the real handler (which converts vdelta windows to base64-encoded
   svndiff data).  The wrapper is responsible for sending the opening
   and closing XML tags around the svndiff data. */
struct window_handler_baton
{
  svn_boolean_t seen_first_window;  /* False until first window seen. */
  update_ctx_t *uc;

  /* The _real_ window handler and baton. */
  svn_txdelta_window_handler_t handler;
  void *handler_baton;
};


/* This implements 'svn_txdelta_window_handler_t'. */
static svn_error_t * window_handler(svn_txdelta_window_t *window, void *baton)
{
  struct window_handler_baton *wb = baton;

  if (! wb->seen_first_window)
    {
      wb->seen_first_window = TRUE;
      SVN_ERR( send_xml(wb->uc, "<S:txdelta>") );
    }

  SVN_ERR( wb->handler(window, wb->handler_baton) );

  if (window == NULL)
    SVN_ERR( send_xml(wb->uc, "</S:txdelta>") );

  return SVN_NO_ERROR;
}


/* This implements 'svn_txdelta_window_handler_t'.
   During a resource walk, the driver sends an empty window as a
   boolean indicating that a change happened to this file, but we
   don't want to send anything over the wire as a result. */
static svn_error_t * dummy_window_handler(svn_txdelta_window_t *window,
                                          void *baton)
{
  return SVN_NO_ERROR;
}


static svn_error_t * upd_apply_textdelta(void *file_baton, 
                                         const char *base_checksum,
                                         apr_pool_t *pool,
                                         svn_txdelta_window_handler_t *handler,
                                         void **handler_baton)
{
  item_baton_t *file = file_baton;
  struct window_handler_baton *wb = apr_palloc(file->pool, sizeof(*wb));
  svn_stream_t *base64_stream;

  if (file->uc->resource_walk)
    {
      *handler = dummy_window_handler;
      *handler_baton = NULL;
      return SVN_NO_ERROR;
    }

  file->base_checksum = apr_pstrdup(file->pool, base_checksum);
  file->text_changed = TRUE;

  wb->seen_first_window = FALSE;
  wb->uc = file->uc;
  base64_stream = dav_svn_make_base64_output_stream(wb->uc->bb, wb->uc->output,
                                                    file->pool);

  svn_txdelta_to_svndiff(base64_stream, file->pool,
                         &(wb->handler), &(wb->handler_baton));

  *handler = window_handler;
  *handler_baton = wb;

  return SVN_NO_ERROR;
}


static svn_error_t * upd_close_file(void *file_baton,
                                    const char *text_checksum,
                                    apr_pool_t *pool)
{
  item_baton_t *file = file_baton;

  file->text_checksum = apr_pstrdup(file->pool, text_checksum);

  /* If we are not in "send all" mode, and this file is not a new
     addition or didn't otherwise have changed text, tell the client
     to fetch it. */
  if ((! file->uc->send_all) && (! file->added) && file->text_changed)
    {
      const char *elt;
      elt = apr_psprintf(pool, "<S:fetch-file%s%s%s/>" DEBUG_CR,
                         file->base_checksum ? " base-checksum=\"" : "",
                         file->base_checksum ? file->base_checksum : "",
                         file->base_checksum ? "\"" : "");
      SVN_ERR( send_xml(file->uc, elt) );
    }

  return close_helper(FALSE /* is_dir */, file);
}


static svn_error_t * upd_close_edit(void *edit_baton,
                                    apr_pool_t *pool)
{
  update_ctx_t *uc = edit_baton;

  /* Our driver will unconditionally close the update report... So if
     the report hasn't even been started yet, start it now. */
  return maybe_start_update_report(uc);
}


dav_error * dav_svn__update_report(const dav_resource *resource,
                                   const apr_xml_doc *doc,
                                   ap_filter_t *output)
{
  svn_delta_editor_t *editor;
  apr_xml_elem *child;
  void *rbaton = NULL;
  update_ctx_t uc = { 0 };
  svn_revnum_t revnum = SVN_INVALID_REVNUM;
  int ns;
  svn_error_t *serr;
  dav_error *derr = NULL;
  apr_status_t apr_err;
  const char *src_path = NULL;
  const char *dst_path = NULL;
  const dav_svn_repos *repos = resource->info->repos;
  const char *target = "";
  svn_boolean_t recurse = TRUE;
  svn_boolean_t resource_walk = FALSE;
  svn_boolean_t ignore_ancestry = FALSE;
  dav_svn_authz_read_baton arb;
  apr_pool_t *subpool = svn_pool_create(resource->pool);

  /* Construct the authz read check baton. */
  arb.r = resource->info->r;
  arb.repos = repos;

  if (resource->info->restype != DAV_SVN_RESTYPE_VCC)
    {
      return dav_new_error_tag(resource->pool, HTTP_CONFLICT, 0,
                               "This report can only be run against a VCC.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }

  ns = dav_svn_find_ns(doc->namespaces, SVN_XML_NAMESPACE);
  if (ns == -1)
    {
      return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
                               "The request does not contain the 'svn:' "
                               "namespace, so it is not going to have an "
                               "svn:target-revision element. That element "
                               "is required.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }
  
  /* Look to see if client wants a report with props and textdeltas
     inline, rather than placeholder tags that tell the client to do
     further fetches.  Modern clients prefer inline. */
  {
    apr_xml_attr *this_attr;

    for (this_attr = doc->root->attr; this_attr; this_attr = this_attr->next)
      {
        if ((strcmp(this_attr->name, "send-all") == 0)
            && (strcmp(this_attr->value, "true") == 0))
          {
            uc.send_all = TRUE;
            break;
          }
      }
  }

  for (child = doc->root->first_child; child != NULL; child = child->next)
    {
      /* Note that child->name might not match any of the cases below.
         Thus, the check for non-empty cdata in each of these cases
         cannot be moved to the top of the loop, because then it would
         wrongly catch other elements that do allow empty cdata. */ 

      if (child->ns == ns && strcmp(child->name, "target-revision") == 0)
        {
          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'target-revision' element contains empty cdata; "
              "there is a problem with the client.",
              SVN_DAV_ERROR_NAMESPACE,
              SVN_DAV_ERROR_TAG);

          /* ### assume no white space, no child elems, etc */
          revnum = SVN_STR_TO_REV(child->first_cdata.first->text);
        }

      if (child->ns == ns && strcmp(child->name, "src-path") == 0)
        {
          /* ### assume no white space, no child elems, etc */
          dav_svn_uri_info this_info;

          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'src-path' element contains empty cdata; "
              "there is a problem with the client.",
              SVN_DAV_ERROR_NAMESPACE,
              SVN_DAV_ERROR_TAG);

          /* split up the 1st public URL. */
          if ((derr = dav_svn__test_canonical
               (child->first_cdata.first->text, resource->pool)))
            return derr;
          serr = dav_svn_simple_parse_uri(&this_info, resource,
                                          child->first_cdata.first->text,
                                          resource->pool);
          if (serr != NULL)
            {
              return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                         "Could not parse src-path URL.",
                                         resource->pool);
            }
          src_path = this_info.repos_path;
        }

      if (child->ns == ns && strcmp(child->name, "dst-path") == 0)
        {
          /* ### assume no white space, no child elems, etc */
          dav_svn_uri_info this_info;

          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'dst-path' element contains empty cdata; "
              "there is a problem with the client.  See "
              "http://subversion.tigris.org/issues/show_bug.cgi?id=1055",
              SVN_DAV_ERROR_NAMESPACE,
              SVN_DAV_ERROR_TAG);

          /* split up the 2nd public URL. */
          if ((derr = dav_svn__test_canonical
               (child->first_cdata.first->text, resource->pool)))
            return derr;
          serr = dav_svn_simple_parse_uri(&this_info, resource,
                                          child->first_cdata.first->text,
                                          resource->pool);
          if (serr != NULL)
            {
              return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                         "Could not parse dst-path URL.",
                                         resource->pool);
            }
          dst_path = this_info.repos_path;
        }

      if (child->ns == ns && strcmp(child->name, "update-target") == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -