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

📄 repos.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
  /*
   * COMB is the resource that we are constructing. Any elements that
   * can be determined from the PATH may be set in COMB. However, further
   * operations are not allowed (we don't want anything besides a parse
   * error to occur).
   *
   * At a minimum, the parse function must set COMB->res.type and
   * COMB->priv.repos_path.
   *
   * PATH does not contain a leading slash. Given "/root/$svn/xxx/the/path"
   * as the request URI, the PATH variable will be "the/path"
   */
  int (*parse)(dav_resource_combined *comb, const char *path,
               const char *label, int use_checked_in);

  /* The number of subcompenents after the !svn/xxx/... before we
     reach the actual path within the repository. */
  int numcomponents;

  /* Boolean:  are the subcomponents followed by a repos path? */
  int has_repos_path;

  /* The private resource type for the /$svn/xxx/ collection. */
  enum dav_svn_private_restype restype;

} special_subdirs[] =
{
  { "ver", dav_svn_parse_version_uri,
    1, TRUE, DAV_SVN_RESTYPE_VER_COLLECTION },
  { "his", dav_svn_parse_history_uri,
    0, FALSE, DAV_SVN_RESTYPE_HIS_COLLECTION },
  { "wrk", dav_svn_parse_working_uri,
    1, TRUE,  DAV_SVN_RESTYPE_WRK_COLLECTION },
  { "act", dav_svn_parse_activity_uri,
    1, FALSE, DAV_SVN_RESTYPE_ACT_COLLECTION },
  { "vcc", dav_svn_parse_vcc_uri,
    1, FALSE, DAV_SVN_RESTYPE_VCC_COLLECTION },
  { "bc", dav_svn_parse_baseline_coll_uri,
    1, TRUE, DAV_SVN_RESTYPE_BC_COLLECTION },
  { "bln", dav_svn_parse_baseline_uri,
    1, FALSE, DAV_SVN_RESTYPE_BLN_COLLECTION },
  { "wbl", dav_svn_parse_wrk_baseline_uri,
    2, FALSE, DAV_SVN_RESTYPE_WBL_COLLECTION },

  { NULL } /* sentinel */
};

/*
 * dav_svn_parse_uri: parse the provided URI into its various bits
 *
 * URI will contain a path relative to our configured root URI. It should
 * not have a leading "/". The root is identified by "".
 *
 * On output: *COMB will contain all of the information parsed out of
 * the URI -- the resource type, activity ID, path, etc.
 *
 * Note: this function will only parse the URI. Validation of the pieces,
 * opening data stores, etc, are not part of this function.
 *
 * TRUE is returned if a parsing error occurred. FALSE for success.
 */
static int dav_svn_parse_uri(dav_resource_combined *comb,
                             const char *uri,
                             const char *label,
                             int use_checked_in)
{
  const char *special_uri = comb->priv.repos->special_uri;
  apr_size_t len1;
  apr_size_t len2;
  char ch;

  len1 = strlen(uri);
  len2 = strlen(special_uri);
  if (len1 > len2
      && ((ch = uri[len2]) == '/' || ch == '\0')
      && memcmp(uri, special_uri, len2) == 0)
    {
      if (ch == '\0')
        {
          /* URI was "/root/!svn". It exists, but has restricted usage. */
          comb->res.type = DAV_RESOURCE_TYPE_PRIVATE;
          comb->priv.restype = DAV_SVN_RESTYPE_ROOT_COLLECTION;
        }
      else
        {
          const struct special_defn *defn;

          /* skip past the "!svn/" prefix */
          uri += len2 + 1;
          len1 -= len2 + 1;

          for (defn = special_subdirs ; defn->name != NULL; ++defn)
            {
              apr_size_t len3 = strlen(defn->name);

              if (len1 >= len3 && memcmp(uri, defn->name, len3) == 0)
                {
                  if (uri[len3] == '\0')
                    {
                      /* URI was "/root/!svn/XXX". The location exists, but
                         has restricted usage. */
                      comb->res.type = DAV_RESOURCE_TYPE_PRIVATE;

                      /* store the resource type so that we can PROPFIND
                         on this collection. */
                      comb->priv.restype = defn->restype;
                    }
                  else if (uri[len3] == '/')
                    {
                      if ((*defn->parse)(comb, uri + len3 + 1, label,
                                         use_checked_in))
                        return TRUE;
                    }
                  else
                    {
                      /* e.g. "/root/!svn/activity" (we just know "act") */
                      return TRUE;
                    }

                  break;
                }
            }

          /* if completed the loop, then it is an unrecognized subdir */
          if (defn->name == NULL)
            return TRUE;
        }
    }
  else
    {
      /* Anything under the root, but not under "!svn". These are all
         version-controlled resources. */
      comb->res.type = DAV_RESOURCE_TYPE_REGULAR;
      comb->res.versioned = TRUE;

      /* The location of these resources corresponds directly to the URI,
         and we keep the leading "/". */
      comb->priv.repos_path = comb->priv.uri_path->data;
    }

  return FALSE;
}

static dav_error * dav_svn_prep_regular(dav_resource_combined *comb)
{
  apr_pool_t *pool = comb->res.pool;
  dav_svn_repos *repos = comb->priv.repos;
  svn_error_t *serr;
  svn_node_kind_t kind;

  /* A REGULAR resource might have a specific revision already (e.g. if it
     is part of a baseline collection). However, if it doesn't, then we
     will assume that we need the youngest revision.
     ### other cases besides a BC? */
  if (comb->priv.root.rev == SVN_INVALID_REVNUM)
    {
      serr = svn_fs_youngest_rev(&comb->priv.root.rev, repos->fs, pool);
      if (serr != NULL)
        {
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not determine the proper "
                                     "revision to access",
                                     pool);
        }
    }

  /* get the root of the tree */
  serr = svn_fs_revision_root(&comb->priv.root.root, repos->fs,
                              comb->priv.root.rev, pool);
  if (serr != NULL)
    {
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "Could not open the root of the "
                                 "repository",
                                 pool);
    }

  serr = svn_fs_check_path(&kind, comb->priv.root.root,
                           comb->priv.repos_path, pool);
  if (serr != NULL)
    {
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 apr_psprintf (pool, "Error checking kind of "
                                               "path '%s' in repository",
                                               comb->priv.repos_path),
                                 pool);
    }

  comb->res.exists = (kind == svn_node_none) ? FALSE : TRUE;
  comb->res.collection = (kind == svn_node_dir) ? TRUE : FALSE;

  return NULL;
}

static dav_error * dav_svn_prep_version(dav_resource_combined *comb)
{
  svn_error_t *serr;
  apr_pool_t *pool = comb->res.pool;

  /* we are accessing the Version Resource by REV/PATH */
  
  /* ### assert: .baselined = TRUE */
  
  /* if we don't have a revision, then assume the youngest */
  if (!SVN_IS_VALID_REVNUM(comb->priv.root.rev))
    {
      serr = svn_fs_youngest_rev(&comb->priv.root.rev,
                                 comb->priv.repos->fs,
                                 pool);
      if (serr != NULL)
        {
          /* ### might not be a baseline */
          
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not fetch 'youngest' revision "
                                     "to enable accessing the latest "
                                     "baseline resource.",
                                     pool);
        }
    }
  
  /* ### baselines have no repos_path, and we don't need to open
     ### a root (yet). we just needed to ensure that we have the proper
     ### revision number. */

  if (!comb->priv.root.root)
    {
      serr = svn_fs_revision_root(&comb->priv.root.root, 
                                  comb->priv.repos->fs,
                                  comb->priv.root.rev,
                                  pool);
      if (serr != NULL)
        {
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "Could not open a revision root.",
                                     pool);
        }
    }

  /* ### we should probably check that the revision is valid */
  comb->res.exists = TRUE;
  
  /* Set up the proper URI. Most likely, we arrived here via a VCC,
     so the URI will be incorrect. Set the canonical form. */
  /* ### assuming a baseline */
  comb->res.uri = dav_svn_build_uri(comb->priv.repos,
                                    DAV_SVN_BUILD_URI_BASELINE,
                                    comb->priv.root.rev, NULL,
                                    0 /* add_href */,
                                    pool);

  return NULL;
}

static dav_error * dav_svn_prep_history(dav_resource_combined *comb)
{
  return NULL;
}

static dav_error * dav_svn_prep_working(dav_resource_combined *comb)
{
  const char *txn_name = dav_svn_get_txn(comb->priv.repos,
                                         comb->priv.root.activity_id);
  apr_pool_t *pool = comb->res.pool;
  svn_error_t *serr;
  svn_node_kind_t kind;

  if (txn_name == NULL)
    {
      /* ### HTTP_BAD_REQUEST is probably wrong */
      return dav_new_error(pool, HTTP_BAD_REQUEST, 0,
                           "An unknown activity was specified in the URL. "
                           "This is generally caused by a problem in the "
                           "client software.");
    }
  comb->priv.root.txn_name = txn_name;

  /* get the FS transaction, given its name */
  serr = svn_fs_open_txn(&comb->priv.root.txn, comb->priv.repos->fs, txn_name,
                         pool);
  if (serr != NULL)
    {
      if (serr->apr_err == SVN_ERR_FS_NO_SUCH_TRANSACTION)
        {
          svn_error_clear(serr);
          return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                               "An activity was specified and found, but the "
                               "corresponding SVN FS transaction was not "
                               "found.");
        }
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "Could not open the SVN FS transaction "
                                 "corresponding to the specified activity.",
                                 pool);
    }

  if (comb->res.baselined)
    {
      /* a Working Baseline */

      /* if the transaction exists, then the working resource exists */
      comb->res.exists = TRUE;

      return NULL;
    }

  /* Set the txn author if not previously set.  Protect against multi-author
   * commits by verifying authenticated user associated with the current
   * request is the same as the txn author.
   * Note that anonymous requests are being excluded as being a change
   * in author, because the commit may touch areas of the repository
   * that are anonymous writeable as well as areas that are not.
   */
  if (comb->priv.repos->username)
    {
      svn_string_t *current_author;
      svn_string_t request_author;

      serr = svn_fs_txn_prop(&current_author, comb->priv.root.txn,
               SVN_PROP_REVISION_AUTHOR, pool);
      if (serr != NULL)
        {
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                   "Failed to retrieve author of the SVN FS transaction "
                   "corresponding to the specified activity.",
                   pool);
        }

      request_author.data = comb->priv.repos->username;
      request_author.len = strlen(request_author.data);
      if (!current_author)
        {
          serr = svn_fs_change_txn_prop(comb->priv.root.txn,
                   SVN_PROP_REVISION_AUTHOR, &request_author, pool);
          if (serr != NULL)
            {
              return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                       "Failed to set the author of the SVN FS transaction "
                       "corresponding to the specified activity.",
                       pool);
            }
        }
      else if (!svn_string_compare(current_author, &request_author))
        {
          return dav_new_error(pool, HTTP_NOT_IMPLEMENTED, 0,
                   "Multi-author commits not supported.");
        }
    }

  /* get the root of the tree */
  serr = svn_fs_txn_root(&comb->priv.root.root, comb->priv.root.txn, pool);
  if (serr != NULL)
    {
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "Could not open the (transaction) root of "
                                 "the repository",
                                 pool);
    }

  serr = svn_fs_check_path (&kind, comb->priv.root.root,
                            comb->priv.repos_path, pool);
  if (serr != NULL)
    {
      return dav_svn_convert_err
        (serr, HTTP_INTERNAL_SERVER_ERROR,
         apr_psprintf (pool, "Error checking kind of path '%s' in repository",
                       comb->priv.repos_path),
         pool);
    }

  comb->res.exists = (kind == svn_node_none) ? FALSE : TRUE;
  comb->res.collection = (kind == svn_node_dir) ? TRUE : FALSE;

⌨️ 快捷键说明

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