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

📄 version.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
      return dav_new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
                               SVN_ERR_UNSUPPORTED_FEATURE,
                               "CHECKOUT can not create an activity at this "
                               "time. Use MKACTIVITY first.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }
  if (is_unreserved)
    {
      return dav_new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
                               SVN_ERR_UNSUPPORTED_FEATURE,
                               "Unreserved checkouts are not yet available. "
                               "A version history may not be checked out more "
                               "than once, into a specific activity.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }
  if (activities == NULL)
    {
      return dav_new_error_tag(resource->pool, HTTP_CONFLICT,
                               SVN_ERR_INCOMPLETE_DATA,
                               "An activity must be provided for checkout.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }
  /* assert: nelts > 0.  the below check effectively means > 1. */
  if (activities->nelts != 1)
    {
      return dav_new_error_tag(resource->pool, HTTP_CONFLICT,
                               SVN_ERR_INCORRECT_PARAMS,
                               "Only one activity may be specified within the "
                               "CHECKOUT.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }

  serr = dav_svn_simple_parse_uri(&parse, resource,
                                  APR_ARRAY_IDX(activities, 0, const char *),
                                  resource->pool);
  if (serr != NULL)
    {
      /* ### is BAD_REQUEST proper? */
      return dav_svn_convert_err(serr, HTTP_CONFLICT,
                                 "The activity href could not be parsed "
                                 "properly.",
                                 resource->pool);
    }
  if (parse.activity_id == NULL)
    {
      return dav_new_error_tag(resource->pool, HTTP_CONFLICT,
                               SVN_ERR_INCORRECT_PARAMS,
                               "The provided href is not an activity URI.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }

  if ((txn_name = dav_svn_get_txn(resource->info->repos,
                                  parse.activity_id)) == NULL)
    {
      return dav_new_error_tag(resource->pool, HTTP_CONFLICT,
                               SVN_ERR_APMOD_ACTIVITY_NOT_FOUND,
                               "The specified activity does not exist.",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }

  /* verify the specified version resource is the "latest", thus allowing
     changes to be made. */
  if (resource->baselined || resource->info->root.rev == SVN_INVALID_REVNUM)
    {
      /* a Baseline, or a standard Version Resource which was accessed
         via a Label against a VCR within a Baseline Collection. */
      /* ### at the moment, this branch is only reached for baselines */

      svn_revnum_t youngest;

      /* make sure the baseline being checked out is the latest */
      serr = svn_fs_youngest_rev(&youngest, resource->info->repos->fs,
                                 resource->pool);
      if (serr != NULL)
        {
          /* ### correct HTTP error? */
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not determine the youngest "
                                     "revision for verification against "
                                     "the baseline being checked out.",
                                     resource->pool);
        }

      if (resource->info->root.rev != youngest)
        {
          return dav_new_error_tag(resource->pool, HTTP_CONFLICT,
                                   SVN_ERR_APMOD_BAD_BASELINE,
                                   "The specified baseline is not the latest "
                                   "baseline, so it may not be checked out.",
                                   SVN_DAV_ERROR_NAMESPACE,
                                   SVN_DAV_ERROR_TAG);
        }

      /* ### hmm. what if the transaction root's revision is different
         ### from this baseline? i.e. somebody created a new revision while
         ### we are processing this commit.
         ###
         ### first question: what does the client *do* with a working
         ### baseline? knowing that, and how it maps to our backend, then
         ### we can figure out what to do here. */
    }
  else
    {
      /* standard Version Resource */

      svn_fs_txn_t *txn;
      svn_fs_root_t *txn_root;
      svn_revnum_t txn_created_rev;
      dav_error *err;

      /* open the specified transaction so that we can verify this version
         resource corresponds to the current/latest in the transaction. */
      if ((err = open_txn(&txn, resource->info->repos->fs, txn_name,
                          resource->pool)) != NULL)
        return err;

      serr = svn_fs_txn_root(&txn_root, txn, resource->pool);
      if (serr != NULL)
        {
          /* ### correct HTTP error? */
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not open the transaction tree.",
                                     resource->pool);
        }

      /* assert: repos_path != NULL (for this type of resource) */


      /* Out-of-dateness check:  compare the created-rev of the item
         in the txn against the created-rev of the version resource
         being changed. */
      serr = svn_fs_node_created_rev(&txn_created_rev,
                                     txn_root, resource->info->repos_path,
                                     resource->pool);
      if (serr != NULL)
        {
          /* ### correct HTTP error? */
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not get created-rev of "
                                     "transaction node.",
                                     resource->pool);
        }

      /* If txn_created_rev is invalid, that means it's already
         mutable in the txn... which means it has already passed this
         out-of-dateness check.  (Usually, this happens when looking
         at a parent directory of an already checked-out
         resource.)  

         Now, we come down to it.  If the created revision of the node
         in the transaction is different from the revision parsed from
         the version resource URL, we're in a bit of a quandry, and
         one of a few things could be true.

         - The client is trying to modify an old (out of date)
           revision of the resource.  This is, of course,
           unacceptable!

         - The client is trying to modify a *newer* revision.  If the
           version resource is *newer* than the transaction root, then
           the client started a commit, a new revision was created
           within the repository, the client fetched the new resource
           from that new revision, changed it (or merged in a prior
           change), and then attempted to incorporate that into the
           commit that was initially started.  We could copy that new
           node into our transaction and then modify it, but why
           bother?  We can stop the commit, and everything will be
           fine again if the user simply restarts it (because we'll
           use that new revision as the transaction root, thus
           incorporating the new resource, which they will then
           modify).
             
         - The path/revision that client is wishing to edit and the
           path/revision in the current transaction are actually the
           same node, and thus this created-rev comparison didn't
           really solidify anything after all. :-)
      */

      if (SVN_IS_VALID_REVNUM( txn_created_rev ))
        {
          int errorful = 0;

          if (resource->info->root.rev < txn_created_rev)
            {
              /* The item being modified is older than the one in the
                 transaction.  The client is out of date.  */
              errorful = 1;
            }
          else if (resource->info->root.rev > txn_created_rev)
            {
              /* The item being modified is being accessed via a newer
                 revision than the one in the transaction.  We'll
                 check to see if they are still the same node, and if
                 not, return an error. */
              const svn_fs_id_t *url_noderev_id, *txn_noderev_id;

              if ((serr = svn_fs_node_id(&txn_noderev_id, txn_root, 
                                         resource->info->repos_path,
                                         resource->pool)))
                {
                  err = dav_new_error_tag
                    (resource->pool, HTTP_CONFLICT, serr->apr_err,
                     "Unable to fetch the node revision id of the version "
                     "resource within the transaction.",
                     SVN_DAV_ERROR_NAMESPACE,
                     SVN_DAV_ERROR_TAG);
                  svn_error_clear(serr);
                  return err;
                }
              if ((serr = svn_fs_node_id(&url_noderev_id,
                                         resource->info->root.root,
                                         resource->info->repos_path,
                                         resource->pool)))
                {
                  err = dav_new_error_tag
                    (resource->pool, HTTP_CONFLICT, serr->apr_err,
                     "Unable to fetch the node revision id of the version "
                     "resource within the revision.",
                     SVN_DAV_ERROR_NAMESPACE,
                     SVN_DAV_ERROR_TAG);
                  svn_error_clear(serr);
                  return err;
                }
              if (svn_fs_compare_ids(url_noderev_id, txn_noderev_id) != 0)
                {
                  errorful = 1;
                }
            }
          if (errorful)
            {
#if 1
              return dav_new_error_tag
                (resource->pool, HTTP_CONFLICT, SVN_ERR_FS_CONFLICT,
                 "The version resource does not correspond to the resource "
                 "within the transaction.  Either the requested version "
                 "resource is out of date (needs to be updated), or the "
                 "requested version resource is newer than the transaction "
                 "root (restart the commit).",
                 SVN_DAV_ERROR_NAMESPACE,
                 SVN_DAV_ERROR_TAG);

#else
              /* ### some debugging code */
              const char *msg;
              
              msg = apr_psprintf(resource->pool, 
                                 "created-rev mismatch: r=%ld, t=%ld",
                                 resource->info->root.rev, txn_created_rev);
              
              return dav_new_error_tag(resource->pool, HTTP_CONFLICT, 
                                       SVN_ERR_FS_CONFLICT, msg,
                                       SVN_DAV_ERROR_NAMESPACE,
                                       SVN_DAV_ERROR_TAG);
#endif
            }
        }
    }
  *working_resource = dav_svn_create_working_resource(resource,
                                                      parse.activity_id,
                                                      txn_name,
                                                      FALSE);
  return NULL;
}

static dav_error *dav_svn_uncheckout(dav_resource *resource)
{
  if (resource->type != DAV_RESOURCE_TYPE_WORKING)
    return dav_new_error_tag(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
                             SVN_ERR_UNSUPPORTED_FEATURE,
                             "UNCHECKOUT called on non-working resource.",
                             SVN_DAV_ERROR_NAMESPACE,
                             SVN_DAV_ERROR_TAG);

  /* Try to abort the txn if it exists;  but don't try too hard.  :-)  */
  if (resource->info->root.txn)
    svn_error_clear(svn_fs_abort_txn(resource->info->root.txn,
                                     resource->pool));

  resource->info->root.txn_name = NULL;
  resource->info->root.txn = NULL;

  /* We're no longer checked out. */
  resource->info->auto_checked_out = FALSE;

  /* Convert the working resource back into a regular one, in-place. */
  return dav_svn_working_to_regular_resource(resource);
}


/* Closure object for cleanup_deltify. */
struct cleanup_deltify_baton
{
  /* The repository in which to deltify.  We use a path instead of an
     object, because it's difficult to obtain a repos or fs object
     with the right lifetime guarantees. */
  const char *repos_path;

  /* The revision number against which to deltify. */
  svn_revnum_t revision;

  /* The pool to use for all temporary allocation while working.  This
     may or may not be the same as the pool on which the cleanup is
     registered, but obviously it must have a lifetime at least as

⌨️ 快捷键说明

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