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

📄 lock.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
         svn_boolean_t under_construction,
         apr_pool_t *pool)
{
  svn_wc_adm_access_t *lock;
  int wc_format;
  svn_error_t *err;

  if (associated)
    {
      adm_ensure_set (associated);

      lock = apr_hash_get (associated->set, path, APR_HASH_KEY_STRING);
      if (lock && lock != &missing)
        /* Already locked.  The reason we don't return the existing baton
           here is that the user is supposed to know whether a directory is
           locked: if it's not locked call svn_wc_adm_open, if it is locked
           call svn_wc_adm_retrieve.  */
        return svn_error_createf (SVN_ERR_WC_LOCKED, NULL,
                                  _("Working copy '%s' locked"),
                                  path);
    }

  if (! under_construction)
    {
      /* By reading the format file we check both that PATH is a directory
         and that it is a working copy. */
      err = svn_io_read_version_file (&wc_format,
                                      svn_wc__adm_path (path, FALSE, pool,
                                                        SVN_WC__ADM_FORMAT,
                                                        NULL),
                                      pool);
      if (err)
        {
          /* Should we attempt to distinguish certain errors? */
          svn_error_clear (err);
          return svn_error_createf (SVN_ERR_WC_NOT_DIRECTORY, NULL,
                                    _("'%s' is not a working copy"),
                                    svn_path_local_style (path, pool));
        }

      SVN_ERR (svn_wc__check_format (wc_format,
                                     svn_path_local_style (path, pool),
                                     pool));
    }

  /* Need to create a new lock */
  if (write_lock)
    {
      lock = adm_access_alloc (svn_wc__adm_access_write_lock, path, pool);
      SVN_ERR (create_lock (lock, 0, pool));
      lock->lock_exists = TRUE;
    }
  else
    {
      lock = adm_access_alloc (svn_wc__adm_access_unlocked, path, pool);
    }

  if (! under_construction)
    {
      lock->wc_format = wc_format;
      if (write_lock)
        SVN_ERR (maybe_upgrade_format (lock, pool));
    }

  if (depth != 0)
    {
      apr_hash_t *entries;
      apr_hash_index_t *hi;
      apr_pool_t *subpool = svn_pool_create (pool);

      /* Reduce depth since we are about to recurse */
      if (depth > 0)
        depth--;
      
      /* Ask for the deleted entries because most operations request them
         at some stage, getting them now avoids a second file parse. */
      SVN_ERR (svn_wc_entries_read (&entries, lock, TRUE, subpool));

      /* Use a temporary hash until all children have been opened. */
      if (associated)
        lock->set = apr_hash_make (subpool);

      /* Open the tree */
      for (hi = apr_hash_first (subpool, entries); hi; hi = apr_hash_next (hi))
        {
          void *val;
          const svn_wc_entry_t *entry;
          svn_wc_adm_access_t *entry_access;
          const char *entry_path;

          apr_hash_this (hi, NULL, NULL, &val);
          entry = val;
          if ((entry->deleted
               && (entry->schedule != svn_wc_schedule_add)
               && (entry->schedule != svn_wc_schedule_replace))
              || entry->kind != svn_node_dir
              || ! strcmp (entry->name, SVN_WC_ENTRY_THIS_DIR))
            continue;
          entry_path = svn_path_join (lock->path, entry->name, subpool);

          /* Don't use the subpool pool here, the lock needs to persist */
          err = do_open (&entry_access, lock, entry_path, write_lock, depth,
                         FALSE, lock->pool);
          if (err)
            {
              if (err->apr_err != SVN_ERR_WC_NOT_DIRECTORY)
                {
                  /* This closes all the children in temporary hash as well */
                  svn_error_clear (svn_wc_adm_close (lock));
                  svn_pool_destroy (subpool);
                  return err;
                }

              /* It's missing or obstructed, so store a placeholder */
              svn_error_clear (err);
              adm_ensure_set (lock);
              apr_hash_set (lock->set, apr_pstrdup (lock->pool, entry_path),
                            APR_HASH_KEY_STRING, &missing);

              continue;
            }

          /* ### Perhaps we should verify that the parent and child agree
             ### about the URL of the child? */
        }

      /* Switch from temporary hash to permanent hash */
      if (associated)
        {
          for (hi = apr_hash_first (subpool, lock->set);
               hi;
               hi = apr_hash_next (hi))
            {
              const void *key;
              void *val;
              const char *entry_path;
              svn_wc_adm_access_t *entry_access;

              apr_hash_this (hi, &key, NULL, &val);
              entry_path = key;
              entry_access = val;
              apr_hash_set (associated->set, entry_path, APR_HASH_KEY_STRING,
                            entry_access);
              entry_access->set = associated->set;
            }
          lock->set = associated->set;
        }
      svn_pool_destroy (subpool);
    }

  if (associated)
    {
      lock->set = associated->set;
      apr_hash_set (lock->set, lock->path, APR_HASH_KEY_STRING, lock);
    }

  /* It's important that the cleanup handler is registered *after* at least
     one UTF8 conversion has been done, since such a conversion may create
     the apr_xlate_t object in the pool, and that object must be around
     when the cleanup handler runs.  If the apr_xlate_t cleanup handler
     were to run *before* the access baton cleanup handler, then the access
     baton's handler won't work. */
  apr_pool_cleanup_register (lock->pool, lock, pool_cleanup,
                             pool_cleanup_child);
  *adm_access = lock;
  return SVN_NO_ERROR;
}

/* To preserve API compatibility with Subversion 1.0.0 */
svn_error_t *
svn_wc_adm_open (svn_wc_adm_access_t **adm_access,
                 svn_wc_adm_access_t *associated,
                 const char *path,
                 svn_boolean_t write_lock,
                 svn_boolean_t tree_lock,
                 apr_pool_t *pool)
{
  return svn_wc_adm_open2 (adm_access, associated, path, write_lock,
                           (tree_lock ? -1 : 0), pool);
}

svn_error_t *
svn_wc_adm_open2 (svn_wc_adm_access_t **adm_access,
                  svn_wc_adm_access_t *associated,
                  const char *path,
                  svn_boolean_t write_lock,
                  int depth,
                  apr_pool_t *pool)
{
  return do_open (adm_access, associated, path, write_lock, depth, FALSE,
                  pool);
}

svn_error_t *
svn_wc__adm_pre_open (svn_wc_adm_access_t **adm_access,
                      const char *path,
                      apr_pool_t *pool)
{
  return do_open (adm_access, NULL, path, TRUE, 0, TRUE, pool);
}


/* To preserve API compatibility with Subversion 1.0.0 */
svn_error_t *
svn_wc_adm_probe_open (svn_wc_adm_access_t **adm_access,
                       svn_wc_adm_access_t *associated,
                       const char *path,
                       svn_boolean_t write_lock,
                       svn_boolean_t tree_lock,
                       apr_pool_t *pool)
{
  return svn_wc_adm_probe_open2 (adm_access, associated, path,
                                 write_lock, (tree_lock ? -1 : 0), pool);
}


svn_error_t *
svn_wc_adm_probe_open2 (svn_wc_adm_access_t **adm_access,
                        svn_wc_adm_access_t *associated,
                        const char *path,
                        svn_boolean_t write_lock,
                        int depth,
                        apr_pool_t *pool)
{
  svn_error_t *err;
  const char *dir;
  int wc_format;

  SVN_ERR (probe (&dir, path, &wc_format, pool));

  /* If we moved up a directory, then the path is not a directory, or it
     is not under version control. In either case, the notion of a depth
     does not apply to the provided path. Disable it so that we don't end
     up trying to lock more than we need.  */
  if (dir != path)
    depth = 0;

  err = svn_wc_adm_open2 (adm_access, associated, dir, write_lock, 
                          depth, pool);
  if (err)
    {
      svn_error_t *err2;

      /* If we got an error on the parent dir, that means we failed to
         get an access baton for the child in the first place.  And if
         the reason we couldn't get the child access baton is that the
         child is not a versioned directory, then return an error
         about the child, not the parent. */ 
      svn_node_kind_t child_kind;
      if ((err2 = svn_io_check_path (path, &child_kind, pool)))
        {
          svn_error_compose (err, err2);
          return err;
        }
  
      if ((dir != path)
          && (child_kind == svn_node_dir)
          && (err->apr_err == SVN_ERR_WC_NOT_DIRECTORY))
        {
          svn_error_clear (err);
          return svn_error_createf (SVN_ERR_WC_NOT_DIRECTORY, NULL,
                                    _("'%s' is not a working copy"),
                                    svn_path_local_style (path, pool));
        }
      else
        {
          return err;
        }
    }

  if (wc_format && ! (*adm_access)->wc_format)
    (*adm_access)->wc_format = wc_format;

  return SVN_NO_ERROR;
}


svn_error_t *
svn_wc__adm_retrieve_internal (svn_wc_adm_access_t **adm_access,
                               svn_wc_adm_access_t *associated,
                               const char *path,
                               apr_pool_t *pool)
{
  if (associated->set)
    *adm_access = apr_hash_get (associated->set, path, APR_HASH_KEY_STRING);
  else if (! strcmp (associated->path, path))
    *adm_access = associated;
  else
    *adm_access = NULL;

  if (*adm_access == &missing)
    *adm_access = NULL;

  return SVN_NO_ERROR;
}

svn_error_t *
svn_wc_adm_retrieve (svn_wc_adm_access_t **adm_access,
                     svn_wc_adm_access_t *associated,
                     const char *path,
                     apr_pool_t *pool)
{
  SVN_ERR (svn_wc__adm_retrieve_internal (adm_access, associated, path, pool));

  /* Most of the code expects access batons to exist, so returning an error
     generally makes the calling code simpler as it doesn't need to check
     for NULL batons. */
  if (! *adm_access)
    return svn_error_createf (SVN_ERR_WC_NOT_LOCKED, NULL,
                              _("Working copy '%s' is missing or not locked"),
                              path);

  return SVN_NO_ERROR;
}


svn_error_t *
svn_wc_adm_probe_retrieve (svn_wc_adm_access_t **adm_access,
                           svn_wc_adm_access_t *associated,
                           const char *path,
                           apr_pool_t *pool)
{
  const char *dir;
  int wc_format;

  SVN_ERR (probe (&dir, path, &wc_format, pool));
  SVN_ERR (svn_wc_adm_retrieve (adm_access, associated, dir, pool));

  if (wc_format && ! (*adm_access)->wc_format)
    (*adm_access)->wc_format = wc_format;

  return SVN_NO_ERROR;
}


/* To preserve API compatibility with Subversion 1.0.0 */
svn_error_t *

⌨️ 快捷键说明

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