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

📄 props.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
  apr_file_t *fp = NULL;

  err = wcprop_list (&prophash, path, adm_access, pool);
  if (err)
    return
      svn_error_quick_wrap
      (err, _("Failed to load properties from disk"));

  /* Now we have all the properties in our hash.  Simply merge the new
     property into it. */
  apr_hash_set (prophash, name, APR_HASH_KEY_STRING, value);

  /* Open the propfile for writing. */
  SVN_ERR (svn_wc__open_props (&fp, 
                               path, /* open in PATH */
                               (APR_WRITE | APR_CREATE | APR_BUFFERED),
                               0, /* not base props */
                               1, /* we DO want wcprops */
                               pool));
  /* Write. */
  SVN_ERR_W (svn_hash_write (prophash, fp, pool),
             apr_psprintf (pool,
                           _("Cannot write property hash for '%s'"), path));
  
  /* Close file, and doing an atomic "move". */
  SVN_ERR (svn_wc__close_props (fp, path, 0, 1,
                                1, /* sync! */
                                pool));

  return SVN_NO_ERROR;
}




/*------------------------------------------------------------------*/

/*** Public Functions ***/


svn_error_t *
svn_wc_prop_list (apr_hash_t **props,
                  const char *path,
                  svn_wc_adm_access_t *adm_access,
                  apr_pool_t *pool)
{
  const char *prop_path;

  *props = apr_hash_make (pool);

  /* Construct a path to the relevant property file */
  SVN_ERR (svn_wc__prop_path (&prop_path, path, adm_access, FALSE, pool));

  /* svn_wc__load_prop_file checks if the prop file exists */
  return svn_wc__load_prop_file (prop_path, *props, pool);
}





svn_error_t *
svn_wc_prop_get (const svn_string_t **value,
                 const char *name,
                 const char *path,
                 svn_wc_adm_access_t *adm_access,
                 apr_pool_t *pool)
{
  svn_error_t *err;
  apr_hash_t *prophash;

  enum svn_prop_kind kind = svn_property_kind (NULL, name);

  if (kind == svn_prop_wc_kind)
    {
      return svn_wc__wcprop_get (value, name, path, adm_access, pool);
    }
  if (kind == svn_prop_entry_kind)
    {
      return svn_error_createf   /* we don't do entry properties here */
        (SVN_ERR_BAD_PROP_KIND, NULL,
         _("Property '%s' is an entry property"), name);
    }
  else  /* regular prop */
    {
      err = svn_wc_prop_list (&prophash, path, adm_access, pool);
      if (err)
        return
          svn_error_quick_wrap
          (err, _("Failed to load properties from disk"));
      
      *value = apr_hash_get (prophash, name, APR_HASH_KEY_STRING);

      return SVN_NO_ERROR;
    }
}


/* The special Subversion properties are not valid for all node kinds.
   Return an error if NAME is an invalid Subversion property for PATH which
   is of kind NODE_KIND. */
static svn_error_t *
validate_prop_against_node_kind (const char *name,
                                 const char *path,
                                 svn_node_kind_t node_kind,
                                 apr_pool_t *pool)
{

  const char *file_prohibit[] = { SVN_PROP_IGNORE,
                                  SVN_PROP_EXTERNALS,
                                  NULL };
  const char *dir_prohibit[] = { SVN_PROP_EXECUTABLE,
                                 SVN_PROP_KEYWORDS,
                                 SVN_PROP_EOL_STYLE,
                                 SVN_PROP_MIME_TYPE,
                                 NULL };
  const char **node_kind_prohibit;

  switch (node_kind)
    {
    case svn_node_dir:
      node_kind_prohibit = dir_prohibit;
      while (*node_kind_prohibit)
        if (strcmp (name, *node_kind_prohibit++) == 0)
          return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, NULL,
                                    _("Cannot set '%s' on a directory (%s)"),
                                    name, path);
      break;
    case svn_node_file:
      node_kind_prohibit = file_prohibit;
      while (*node_kind_prohibit)
        if (strcmp (name, *node_kind_prohibit++) == 0)
          return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, NULL,
                                    _("Cannot set '%s' on a file (%s)"),
                                    name, path);
      break;
    default:
      return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                                _("'%s' is not a file or directory"), path);
    }

  return SVN_NO_ERROR;
}                             


static svn_error_t *
validate_eol_prop_against_file (const char *path, 
                                svn_wc_adm_access_t *adm_access,
                                apr_pool_t *pool)
{
  apr_file_t *fp;
  svn_stream_t *read_stream, *write_stream;
  svn_error_t *err;
  const svn_string_t *mime_type;

  /* See if this file has been determined to be binary. */
  SVN_ERR (svn_wc_prop_get (&mime_type, SVN_PROP_MIME_TYPE, path, adm_access,
                            pool));
  if (mime_type && svn_mime_type_is_binary (mime_type->data))
    return svn_error_createf 
      (SVN_ERR_ILLEGAL_TARGET, NULL,
       _("File '%s' has binary mime type property"), path);

  /* Open PATH. */
  SVN_ERR (svn_io_file_open (&fp, path, 
                             (APR_READ | APR_BINARY | APR_BUFFERED),
                             0, pool));

  /* Get a READ_STREAM from the file we just opened. */
  read_stream = svn_stream_from_aprfile (fp, pool);

  /* Now, make an empty WRITE_STREAM. */
  write_stream = svn_stream_empty (pool);

  /* Do a newline translation.  Of course, all we really care about
     here is whether or not the function fails on inconsistent line
     endings.  The function is "translating" to an empty stream.  This
     is sneeeeeeeeeeeaky. */
  err = svn_subst_translate_stream (read_stream, write_stream, 
                                    "", FALSE, NULL, FALSE);
  if (err && err->apr_err == SVN_ERR_IO_INCONSISTENT_EOL)
    return svn_error_createf (SVN_ERR_ILLEGAL_TARGET, err,
                              _("File '%s' has inconsistent newlines"), path);
  else if (err)
    return err;

  SVN_ERR (svn_io_file_close (fp, pool));
  return SVN_NO_ERROR;
}


svn_error_t *
svn_wc_prop_set (const char *name,
                 const svn_string_t *value,
                 const char *path,
                 svn_wc_adm_access_t *adm_access,
                 apr_pool_t *pool)
{
  svn_error_t *err;
  apr_hash_t *prophash;
  apr_file_t *fp = NULL;
  svn_subst_keywords_t *old_keywords;
  svn_stringbuf_t *new_value = NULL;
  svn_node_kind_t kind;
  enum svn_prop_kind prop_kind = svn_property_kind (NULL, name);

  SVN_ERR (svn_io_check_path (path, &kind, pool));

  if (prop_kind == svn_prop_wc_kind)
    return svn_wc__wcprop_set (name, value, path, adm_access, pool);
  else if (prop_kind == svn_prop_entry_kind)
    return svn_error_createf   /* we don't do entry properties here */
      (SVN_ERR_BAD_PROP_KIND, NULL,
       _("Property '%s' is an entry property"), name);

  /* Else, handle a regular property: */

  /* Setting an inappropriate property is not allowed, deleting such a
     property is allowed since older clients allowed (and other clients
     possibly still allow) setting it. */
  if (value)
    {
      SVN_ERR (validate_prop_against_node_kind (name, path, kind, pool));
      if (strcmp (name, SVN_PROP_EOL_STYLE) == 0)
        {
          new_value = svn_stringbuf_create_from_string (value, pool);
          svn_stringbuf_strip_whitespace (new_value);
          SVN_ERR (validate_eol_prop_against_file (path, adm_access, pool));
        }
      else if (strcmp (name, SVN_PROP_MIME_TYPE) == 0)
        {
          new_value = svn_stringbuf_create_from_string (value, pool);
          svn_stringbuf_strip_whitespace (new_value);
          SVN_ERR (svn_mime_type_validate (new_value->data, pool));
        }
      else if (strcmp (name, SVN_PROP_IGNORE) == 0
               || strcmp (name, SVN_PROP_EXTERNALS) == 0)
        {
          /* Make sure that the last line ends in a newline */
          if (value->data[value->len - 1] != '\n')
            {
              new_value = svn_stringbuf_create_from_string (value, pool);
              svn_stringbuf_appendbytes (new_value, "\n", 1);
            }

          /* Make sure this is a valid externals property. */
          if (strcmp (name, SVN_PROP_EXTERNALS) == 0)
            {
              /* We don't allow "." nor ".." as target directories in
                 an svn:externals line.  As it happens, our parse code
                 checks for this, so all we have to is invoke it --
                 we're not interested in the parsed result, only in
                 whether or the parsing errored. */
              SVN_ERR (svn_wc_parse_externals_description2
                       (NULL, path, value->data, pool));
            }
        }
      else if (strcmp (name, SVN_PROP_KEYWORDS) == 0)
        {
          new_value = svn_stringbuf_create_from_string (value, pool);
          svn_stringbuf_strip_whitespace (new_value);
        }
    }

  if (kind == svn_node_file && strcmp (name, SVN_PROP_EXECUTABLE) == 0)
    {
      /* If the svn:executable property was set, then chmod +x.
         If the svn:executable property was deleted (NULL value passed
         in), then chmod -x. */
      if (value == NULL)
        {
          SVN_ERR (svn_io_set_file_executable (path, FALSE, TRUE, pool));
        }
      else
        {
          /* Since we only check if the property exists or not, force the
             property value to a specific value */
          static const svn_string_t executable_value =
            {
              SVN_PROP_EXECUTABLE_VALUE,
              sizeof (SVN_PROP_EXECUTABLE_VALUE) - 1
            };

          value = &executable_value;
          SVN_ERR (svn_io_set_file_executable (path, TRUE, TRUE, pool));
        }
    }

  err = svn_wc_prop_list (&prophash, path, adm_access, pool);
  if (err)
    return
      svn_error_quick_wrap
      (err, _("Failed to load properties from disk"));

  /* If we're changing this file's list of expanded keywords, then
   * we'll need to invalidate its text timestamp, since keyword
   * expansion affects the comparison of working file to text base.
   *
   * Here we retrieve the old list of expanded keywords; after the
   * property is set, we'll grab the new list and see if it differs
   * from the old one.
   */
  if (kind == svn_node_file && strcmp (name, SVN_PROP_KEYWORDS) == 0)
    SVN_ERR (svn_wc__get_keywords (&old_keywords, path, adm_access, NULL,
                                   pool));

  /* Now we have all the properties in our hash.  Simply merge the new
     property into it. */
  if (new_value)
    value = svn_string_create_from_buf (new_value, pool);
  apr_hash_set (prophash, name, APR_HASH_KEY_STRING, value);
  
  /* Open the propfile for writing. */
  SVN_ERR (svn_wc__open_props (&fp, 
                               path, /* open in PATH */
                               (APR_WRITE | APR_CREATE | APR_BUFFERED),
                               0, /* not base props */
                               0, /* not wcprops */
                               pool));
  /* Write. */
  SVN_ERR_W (svn_hash_write (prophash, fp, pool),
             apr_psprintf (pool, 
                           _("Cannot write property hash for '%s'"), path));
  
  /* Close file, and doing an atomic "move". */
  SVN_ERR (svn_wc__close_props (fp, path, 0, 0,
                                1, /* sync! */
                                pool));

  if (kind == svn_node_file && strcmp (name, SVN_PROP_KEYWORDS) == 0)
    {
      svn_subst_keywords_t *new_keywords;
      SVN_ERR (svn_wc__get_keywords (&new_keywords, path, adm_access, NULL,
                                     pool));

      if (svn_subst_keywords_differ (old_keywords, new_keywords, FALSE))
        {
          const char *base_name;
          svn_wc_entry_t tmp_entry;

          /* If we changed the keywords or newlines, void the entry
             timestamp for this file, so svn_wc_text_modified_p() does
             a real (albeit slow) check later on. */
          svn_path_split (path, NULL, &base_name, pool);
          tmp_entry.kind = svn_node_file;
          tmp_entry.text_time = 0;
          SVN_ERR (svn_wc__entry_modify (adm_access, base_name, &tmp_entry,
                                         SVN_WC__ENTRY_MODIFY_TEXT_TIME,
                                         TRUE, pool));
        }
    }

  return SVN_NO_ERROR;
}


svn_boolean_t
svn_wc_is_normal_prop (const char *name)
{
  enum svn_prop_kind kind = svn_property_kind (NULL, name);
  return (kind == svn_prop_regular_kind);
}


svn_boolean_t
svn_wc_is_wc_prop (const char *name)
{
  enum svn_prop_kind kind = svn_property_kind (NULL, name);
  return (kind == svn_prop_wc_kind);
}


svn_boolean_t
svn_wc_is_entry_prop (const char *name)
{
  enum svn_prop_kind kind = svn_property_kind (NULL, name);
  return (kind == svn_prop_entry_kind);
}


/* Helper to optimize svn_wc_props_modified_p().

   If PATH_TO_PROP_FILE is nonexistent, or is of size 4 bytes ("END"),
   then set EMPTY_P to true.   Otherwise set EMPTY_P to false, which
   means that the file must contain real properties.  */
static svn_error_t *
empty_props_p (svn_boolean_t *empty_p,
               const char *path_to_prop_file,
               apr_pool_t *pool)
{
  svn_error_t *err;
  apr_finfo_t finfo;

  err = svn_io_stat (&finfo, path_to_prop_file, APR_FINFO_MIN | APR_FINFO_TYPE,
                     pool);
  if (err)

⌨️ 快捷键说明

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