blob: 809de23faa43c71d868bb7ea98088869db4daa2a [file] [log] [blame]
/*
* prop_commands.c: Implementation of propset, propget, and proplist.
*
* ====================================================================
* Copyright (c) 2000-2002 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
/* ==================================================================== */
/*** Includes. ***/
#define APR_WANT_STRFUNC
#include <apr_want.h>
#include "svn_client.h"
#include "client.h"
#include "svn_path.h"
/*** Code. ***/
svn_error_t *
svn_client_propset (const char *propname,
const svn_string_t *propval,
const char *target,
svn_boolean_t recurse,
apr_pool_t *pool)
{
svn_wc_entry_t *node;
/* ### be nice to avoid this */
svn_stringbuf_t *target_buf = svn_stringbuf_create (target, pool);
SVN_ERR (svn_wc_entry (&node, target_buf, pool));
if (!node)
return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
"'%s' -- not a versioned resource",
target);
if (recurse && node->kind == svn_node_dir)
{
apr_hash_t *entries;
apr_hash_index_t *hi;
SVN_ERR (svn_wc_entries_read (&entries, target_buf, pool));
for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
{
const void *key;
const char *keystring;
apr_ssize_t klen;
void * val;
const char *current_entry_name;
svn_stringbuf_t *full_entry_path = svn_stringbuf_create (target,
pool);
svn_wc_entry_t *current_entry;
apr_hash_this (hi, &key, &klen, &val);
keystring = key;
current_entry = val;
if (! strcmp (keystring, SVN_WC_ENTRY_THIS_DIR))
current_entry_name = NULL;
else
current_entry_name = keystring;
/* Compute the complete path of the entry */
if (current_entry_name)
svn_path_add_component_nts (full_entry_path, current_entry_name);
if (current_entry->schedule != svn_wc_schedule_delete)
{
if (current_entry->kind == svn_node_dir && current_entry_name)
{
SVN_ERR (svn_client_propset (propname, propval,
full_entry_path->data, recurse,
pool));
}
else
{
SVN_ERR (svn_wc_prop_set (propname, propval,
full_entry_path->data, pool));
}
}
}
}
else
{
SVN_ERR (svn_wc_prop_set (propname, propval, target, pool));
}
return SVN_NO_ERROR;
}
/* Helper for svn_client_propget. */
static svn_error_t *
recursive_propget (apr_hash_t *props,
const char *propname,
svn_stringbuf_t *target,
apr_pool_t *pool)
{
apr_hash_t *entries;
apr_hash_index_t *hi;
SVN_ERR (svn_wc_entries_read (&entries, target, pool));
for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
{
const void *key;
const char *keystring;
apr_ssize_t klen;
void * val;
const char *current_entry_name;
svn_stringbuf_t *full_entry_path = svn_stringbuf_dup (target, pool);
svn_wc_entry_t *current_entry;
apr_hash_this (hi, &key, &klen, &val);
keystring = key;
current_entry = val;
if (! strcmp (keystring, SVN_WC_ENTRY_THIS_DIR))
current_entry_name = NULL;
else
current_entry_name = keystring;
/* Compute the complete path of the entry */
if (current_entry_name)
svn_path_add_component_nts (full_entry_path, current_entry_name);
if (current_entry->schedule != svn_wc_schedule_delete)
{
if (current_entry->kind == svn_node_dir && current_entry_name)
{
SVN_ERR (recursive_propget (props, propname,
full_entry_path, pool));
}
else
{
const svn_string_t *propval;
SVN_ERR (svn_wc_prop_get (&propval,
propname,
full_entry_path->data,
pool));
if (propval)
apr_hash_set (props,
full_entry_path->data,
full_entry_path->len,
propval);
}
}
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_propget (apr_hash_t **props,
const char *propname,
const char *target,
svn_boolean_t recurse,
apr_pool_t *pool)
{
apr_hash_t *prop_hash = apr_hash_make (pool);
svn_wc_entry_t *node;
/* ### be nice to avoid this */
svn_stringbuf_t *target_buf = svn_stringbuf_create (target, pool);
SVN_ERR (svn_wc_entry (&node, target_buf, pool));
if (!node)
return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
"'%s' -- not a versioned resource", target);
if (recurse && node->kind == svn_node_dir)
{
SVN_ERR (recursive_propget (prop_hash, propname, target_buf, pool));
}
else
{
const svn_string_t *propval;
SVN_ERR (svn_wc_prop_get (&propval, propname, target, pool));
if (propval)
apr_hash_set (prop_hash, target, APR_HASH_KEY_STRING, propval);
}
*props = prop_hash;
return SVN_NO_ERROR;
}
/* Helper for svn_client_proplist, and recursive_proplist. */
static svn_error_t *
add_to_proplist (apr_array_header_t *prop_list,
const char *node_name,
apr_pool_t *pool)
{
apr_hash_t *hash;
SVN_ERR (svn_wc_prop_list (&hash, node_name, pool));
if (hash && apr_hash_count (hash))
{
svn_client_proplist_item_t *item
= apr_palloc(pool, sizeof(svn_client_proplist_item_t));
item->node_name = svn_stringbuf_create (node_name, pool);
item->prop_hash = hash;
*((svn_client_proplist_item_t **)apr_array_push(prop_list)) = item;
}
return SVN_NO_ERROR;
}
/* Helper for svn_client_proplist. */
static svn_error_t *
recursive_proplist (apr_array_header_t *props,
svn_stringbuf_t *target,
apr_pool_t *pool)
{
apr_hash_t *entries;
apr_hash_index_t *hi;
SVN_ERR (svn_wc_entries_read (&entries, target, pool));
for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
{
const void *key;
const char *keystring;
apr_ssize_t klen;
void * val;
const char *current_entry_name;
svn_stringbuf_t *full_entry_path = svn_stringbuf_dup (target, pool);
svn_wc_entry_t *current_entry;
apr_hash_this (hi, &key, &klen, &val);
keystring = key;
current_entry = val;
if (! strcmp (keystring, SVN_WC_ENTRY_THIS_DIR))
current_entry_name = NULL;
else
current_entry_name = keystring;
/* Compute the complete path of the entry */
if (current_entry_name)
svn_path_add_component_nts (full_entry_path, current_entry_name);
if (current_entry->schedule != svn_wc_schedule_delete)
{
if (current_entry->kind == svn_node_dir && current_entry_name)
SVN_ERR (recursive_proplist (props, full_entry_path, pool));
else
SVN_ERR (add_to_proplist (props, full_entry_path->data, pool));
}
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_client_proplist (apr_array_header_t **props,
const char *target,
svn_boolean_t recurse,
apr_pool_t *pool)
{
apr_array_header_t *prop_list
= apr_array_make (pool, 5, sizeof (svn_client_proplist_item_t *));
svn_wc_entry_t *entry;
/* ### be nice to avoid this */
svn_stringbuf_t *target_buf = svn_stringbuf_create (target, pool);
SVN_ERR (svn_wc_entry (&entry, target_buf, pool));
if (! entry)
return svn_error_createf (SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
"'%s' -- not a versioned resource",
target);
if (recurse && entry->kind == svn_node_dir)
SVN_ERR (recursive_proplist (prop_list, target_buf, pool));
else
SVN_ERR (add_to_proplist (prop_list, target, pool));
*props = prop_list;
return SVN_NO_ERROR;
}
/*
* local variables:
* eval: (load-file "../../../tools/dev/svn-dev.el")
* end: */