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

📄 update.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
        {
          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'update-target' 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 */
          if ((derr = dav_svn__test_canonical
               (child->first_cdata.first->text, resource->pool)))
            return derr;
          target = child->first_cdata.first->text;
        }
      if (child->ns == ns && strcmp(child->name, "recursive") == 0)
        {
          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'recursive' 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 */
          if (strcmp(child->first_cdata.first->text, "no") == 0)
            recurse = FALSE;
        }
      if (child->ns == ns && strcmp(child->name, "ignore-ancestry") == 0)
        {
          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'ignore-ancestry' 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 */
          ignore_ancestry = TRUE;
          if (strcmp(child->first_cdata.first->text, "no") == 0)
            ignore_ancestry = FALSE;
        }
      if (child->ns == ns && strcmp(child->name, "resource-walk") == 0)
        {
          if (! child->first_cdata.first)
            return dav_new_error_tag(resource->pool, HTTP_BAD_REQUEST, 0,
              "The request's 'resource-walk' 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 */
          if (strcmp(child->first_cdata.first->text, "no") != 0)
            resource_walk = TRUE;
        }
    }

  if (revnum == SVN_INVALID_REVNUM)
    {
      serr = svn_fs_youngest_rev(&revnum, repos->fs, resource->pool);
      if (serr != NULL)
        {
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not determine the youngest "
                                     "revision for the update process.",
                                     resource->pool);
        }
    }

  editor = svn_delta_default_editor(resource->pool);
  editor->set_target_revision = upd_set_target_revision;
  editor->open_root = upd_open_root;
  editor->delete_entry = upd_delete_entry;
  editor->add_directory = upd_add_directory;
  editor->open_directory = upd_open_directory;
  editor->change_dir_prop = upd_change_xxx_prop;
  editor->close_directory = upd_close_directory;
  editor->absent_directory = upd_absent_directory;
  editor->add_file = upd_add_file;
  editor->open_file = upd_open_file;
  editor->apply_textdelta = upd_apply_textdelta;
  editor->change_file_prop = upd_change_xxx_prop;
  editor->close_file = upd_close_file;
  editor->absent_file = upd_absent_file;
  editor->close_edit = upd_close_edit;

  /* If the client never sent a <src-path> element, it's old and
     sending a style of report that we no longer allow. */
  if (! src_path)
    {
      return dav_new_error_tag
        (resource->pool, HTTP_BAD_REQUEST, 0,
         "The request did not contain the '<src-path>' element.\n"
         "This may indicate that your client is too old.",
         SVN_DAV_ERROR_NAMESPACE,
         SVN_DAV_ERROR_TAG);
    }

  uc.resource = resource;
  uc.output = output;  
  uc.anchor = src_path;
  uc.target = target;
  uc.bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
  uc.pathmap = NULL;
  if (dst_path) /* we're doing a 'switch' */
    {      
      if (*target)
        {
          /* if the src is split into anchor/target, so must the
             telescoping dst_path be. */
          uc.dst_path = svn_path_dirname(dst_path, resource->pool);

          /* Also, the svn_repos_dir_delta() is going to preserve our
             target's name, so we need a pathmap entry for that. */
          if (! uc.pathmap)
            uc.pathmap = apr_hash_make(resource->pool);
          add_to_path_map(uc.pathmap, 
                          svn_path_join(src_path, target, resource->pool),
                          dst_path);
        }
      else
        {
          uc.dst_path = dst_path;
        }
    }
  else  /* we're doing an update, so src and dst are the same. */
    uc.dst_path = uc.anchor;

  /* Get the root of the revision we want to update to. This will be used
     to generated stable id values. */
  if ((serr = svn_fs_revision_root(&uc.rev_root, repos->fs, 
                                   revnum, resource->pool)))
    {
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "The revision root could not be created.",
                                 resource->pool);
    }

  /* When we call svn_repos_finish_report, it will ultimately run
     dir_delta() between REPOS_PATH/TARGET and TARGET_PATH.  In the
     case of an update or status, these paths should be identical.  In
     the case of a switch, they should be different. */
  if ((serr = svn_repos_begin_report(&rbaton, revnum, repos->username, 
                                     repos->repos, 
                                     src_path, target,
                                     dst_path,
                                     uc.send_all,
                                     recurse,
                                     ignore_ancestry,
                                     editor, &uc,
                                     dav_svn_authz_read,
                                     &arb,
                                     resource->pool)))
    {
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "The state report gatherer could not be "
                                 "created.",
                                 resource->pool);
    }

  /* scan the XML doc for state information */
  for (child = doc->root->first_child; child != NULL; child = child->next)
    if (child->ns == ns)
      {
        /* Clear our subpool. */
        svn_pool_clear(subpool);

        if (strcmp(child->name, "entry") == 0)
          {
            const char *path;
            svn_revnum_t rev = SVN_INVALID_REVNUM;
            const char *linkpath = NULL;
            svn_boolean_t start_empty = FALSE;
            apr_xml_attr *this_attr = child->attr;

            while (this_attr)
              {
                if (! strcmp(this_attr->name, "rev"))
                  rev = SVN_STR_TO_REV(this_attr->value);
                else if (! strcmp(this_attr->name, "linkpath"))
                  linkpath = this_attr->value;
                else if (! strcmp(this_attr->name, "start-empty"))
                  start_empty = TRUE;

                this_attr = this_attr->next;
              }
            
            /* we require the `rev' attribute for this to make sense */
            if (! SVN_IS_VALID_REVNUM (rev))
              {
                serr = svn_error_create (SVN_ERR_XML_ATTRIB_NOT_FOUND, 
                                         NULL, "Missing XML attribute: rev");
                derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                           "A failure occurred while "
                                           "recording one of the items of "
                                           "working copy state.",
                                           resource->pool);
                goto cleanup;
              }

            /* get cdata, stripping whitespace */
            path = dav_xml_get_cdata(child, subpool, 1);
            
            if (! linkpath)
              serr = svn_repos_set_path(rbaton, path, rev,
                                        start_empty, subpool);
            else
              serr = svn_repos_link_path(rbaton, path, linkpath, rev,
                                         start_empty, subpool);
            if (serr != NULL)
              {
                derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                           "A failure occurred while "
                                           "recording one of the items of "
                                           "working copy state.",
                                           resource->pool);
                goto cleanup;
              }

            /* now, add this path to our path map, but only if we are
               doing a regular update (not a `switch') */
            if (linkpath && (! dst_path))
              {
                const char *this_path;
                if (! uc.pathmap)
                  uc.pathmap = apr_hash_make(resource->pool);
                this_path = svn_path_join_many(apr_hash_pool_get(uc.pathmap),
                                               src_path, target, path, NULL);
                add_to_path_map(uc.pathmap, this_path, linkpath);
              }
          }
        else if (strcmp(child->name, "missing") == 0)
          {
            /* get cdata, stripping whitespace */
            const char *path = dav_xml_get_cdata(child, subpool, 1);
            serr = svn_repos_delete_path(rbaton, path, subpool);
            if (serr != NULL)
              {
                derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                           "A failure occurred while "
                                           "recording one of the (missing) "
                                           "items of working copy state.",
                                           resource->pool);
                goto cleanup;
              }
          }
      }

  /* this will complete the report, and then drive our editor to generate
     the response to the client. */
  serr = svn_repos_finish_report(rbaton, resource->pool);
  if (serr)
    {
      derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "A failure occurred while "
                                 "driving the update report editor",
                                 resource->pool);
      goto cleanup;
    }

  /* We're finished with the report baton.  Note that so we don't try
     to abort this report later. */
  rbaton = NULL;

  /* ### Temporarily disable resource_walks for single-file switch
     operations.  It isn't strictly necessary. */
  if (dst_path && resource_walk)
    {
      /* Sanity check: if we switched a file, we can't do a resource
         walk.  dir_delta would choke if we pass a filepath as the
         'target'.  Also, there's no need to do the walk, since the
         new vsn-rsc-url was already in the earlier part of the report. */
      svn_node_kind_t dst_kind;
      if ((serr = svn_fs_check_path(&dst_kind, uc.rev_root, dst_path,
                                    resource->pool)))
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Failed checking destination path kind.",
                                     resource->pool);
          goto cleanup;
        }
      if (dst_kind != svn_node_dir)
        resource_walk = FALSE;
    }

  /* The potential "resource walk" part of the update-report. */
  if (dst_path && resource_walk)  /* this was a 'switch' operation */
    {
      /* send a second embedded <S:resource-walk> tree that contains
         the new vsn-rsc-urls for the switched dir.  this walk
         contains essentially nothing but <add> tags. */
      svn_fs_root_t *zero_root;
      serr = svn_fs_revision_root(&zero_root, repos->fs, 0,
                                  resource->pool);
      if (serr)
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Failed to find the revision root",
                                     resource->pool);
          goto cleanup;
        }

      serr = send_xml(&uc, "<S:resource-walk>" DEBUG_CR);
      if (serr)
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Unable to begin resource walk",
                                     resource->pool);
          goto cleanup;
        }

      uc.resource_walk = TRUE;

      /* Compare subtree DST_PATH within a pristine revision to
         revision 0.  This should result in nothing but 'add' calls
         to the editor. */
      serr = svn_repos_dir_delta(zero_root, "", target,
                                 uc.rev_root, dst_path,
                                 /* re-use the editor */
                                 editor, &uc, dav_svn_authz_read,
                                 &arb, FALSE /* text-deltas */, recurse, 
                                 TRUE /* entryprops */, 
                                 FALSE /* ignore-ancestry */, resource->pool);
      if (serr)
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Resource walk failed.", resource->pool);
          goto cleanup;
        }
          
      serr = send_xml(&uc, "</S:resource-walk>" DEBUG_CR);
      if (serr)
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Unable to complete resource walk.",
                                     resource->pool);
          goto cleanup;
        }
    }

  /* Close the report body, unless some error prevented it from being
     started in the first place. */
  if (uc.started_update)
    {
      serr = send_xml(&uc, "</S:update-report>" DEBUG_CR);
      if (serr)
        {
          derr = dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Unable to complete update report.",
                                     resource->pool);
          goto cleanup;
        }
    }

 cleanup:

  /* Flush the contents of the brigade (returning an error only if we
     don't already have one). */
  if ((! derr) && ((apr_err = ap_fflush(output, uc.bb))))
    derr = dav_svn_convert_err(svn_error_create(apr_err, 0, NULL),
                               HTTP_INTERNAL_SERVER_ERROR,
                               "Error flushing brigade.",
                               resource->pool);

  /* if an error was produced EITHER by the dir_delta drive or the
     resource-walker... */
  if (derr)
    {
      if (rbaton)
        svn_error_clear(svn_repos_abort_report(rbaton, resource->pool));
      return derr;
    }

  /* Destroy our subpool. */
  svn_pool_destroy(subpool);

  return NULL;
}

⌨️ 快捷键说明

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