I'll send test case for these functions separately. I've
made several changes to fs-test.c and breaking that into
pieces is not so easy.
* dag.c (svn_fs__dag_get_proplist): Return real proplist.
* dag.c (svn_fs__dag_set_proplist): Insert proplist
properly. Remove obsolete comment.
* tree.c (struct proplist_args): New structure for
svn_fs_node_proplist.
* tree.c (txn_body_node_proplist): New helper function for
svn_fs_node_proplist.
* tree.c (svn_fs_node_proplist): Fill in this function.
* tree.c (txn_body_change_node_prop): Implement promise that
property will be removed when value is NULL.
Index: subversion/libsvn_fs/dag.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.c,v
retrieving revision 1.70
diff -u -r1.70 dag.c
--- subversion/libsvn_fs/dag.c 2001/03/03 21:10:13 1.70
+++ subversion/libsvn_fs/dag.c 2001/03/05 03:59:27
@@ -472,7 +472,7 @@
header = node_rev->children;
/* The property list is the 2nd item in the header skel. */
- *proplist_p = header->next;
+ *proplist_p = header->children->next;
return SVN_NO_ERROR;
}
@@ -532,9 +532,7 @@
header = node_rev->children;
/* Insert the new proplist into the content_skel. */
- /* jimb: Watch out! Once we've got content caching working, this
- will be changing the cached skel. If the operation below fails
- or deadlocks, the cache will be wrong. */
+ proplist->next = header->children->next->next;
header->children->next = proplist;
/* Commit the new content_skel, within the given trail. */
Index: subversion/libsvn_fs/tree.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/tree.c,v
retrieving revision 1.30
diff -u -r1.30 tree.c
--- subversion/libsvn_fs/tree.c 2001/03/02 22:05:06 1.30
+++ subversion/libsvn_fs/tree.c 2001/03/05 03:59:27
@@ -653,13 +652,59 @@
}
+struct node_proplist_args {
+ apr_hash_t **table_p;
+ svn_fs_root_t *root;
+ const char *path;
+};
+
+
+static svn_error_t *
+txn_body_node_proplist (void *baton, trail_t *trail)
+{
+ struct node_proplist_args *args = baton;
+
+ parent_path_t *parent_path;
+ apr_hash_t *table;
+ skel_t *proplist, *prop;
+
+ SVN_ERR (open_path (&parent_path, args->root, args->path, 0, trail));
+ SVN_ERR (svn_fs__dag_get_proplist (&proplist, parent_path->node, trail));
+
+ /* Build a hash table from the property list. */
+ table = apr_hash_make (trail->pool);
+ for (prop = proplist->children; prop; prop = prop->next->next)
+ {
+ skel_t *name = prop;
+ skel_t *value = prop->next;
+
+ apr_hash_set (table, name->data, name->len,
+ svn_string_ncreate (value->data, value->len,
+ trail->pool));
+ }
+
+ *args->table_p = table;
+ return SVN_NO_ERROR;
+}
+
+
svn_error_t *
svn_fs_node_proplist (apr_hash_t **table_p,
svn_fs_root_t *root,
const char *path,
apr_pool_t *pool)
{
- abort ();
+ apr_hash_t *table;
+ struct node_proplist_args args;
+
+ args.table_p = &table;
+ args.root = root;
+ args.path = path;
+
+ SVN_ERR (svn_fs__retry_txn (root->fs, txn_body_node_proplist, &args, pool));
+
+ *table_p = table;
+ return SVN_NO_ERROR;
}
@@ -678,6 +723,7 @@
struct change_node_prop_args *args = baton;
parent_path_t *parent_path;
skel_t *proplist, *prop;
+ skel_t *prev = NULL;
SVN_ERR (open_path (&parent_path, args->root, args->path, 0, trail));
SVN_ERR (make_path_mutable (args->root, parent_path, args->path, trail));
@@ -689,16 +735,54 @@
skel_t *name = prop;
skel_t *value = prop->next;
- /* We've found an existing entry for this property.
- Replace the value. */
- if (name->len == args->name->len
- && ! memcmp (name->data, args->name->data, name->len))
+ if (svn_fs__atom_matches_string (name, args->name))
{
- value->data = args->value->data;
- value->len = args->value->len;
+ /* We've found an existing entry for this property. */
+ if (! args->value)
+ {
+ /* If our new value for this is NULL, we'll remove the
+ property altogether by effectively routing our linked
+ list of properties around the current property
+ name/value pair. */
+ if (prev)
+ {
+ /* If this isn't the first pair in the list, this
+ can be done by setting the previous value's next
+ pointer to the name of the following property
+ pair, if one exists, or zero if we are removing
+ the last name/value pair currently in the
+ list. */
+ if (prop->next)
+ prev->next->next = prop->next->next;
+ else
+ prev->next->next = 0;
+ }
+ else
+ {
+ /* If, however, this is the first item in the list,
+ we'll set the children pointer of the PROPLIST
+ skel to the following name/value pair, if one
+ exists, or zero if we're removing the only
+ property pair in the list. */
+ if (prop->next)
+ proplist->children = prop->next->next;
+ else
+ proplist->children = 0;
+ }
+ }
+ else
+ {
+ value->data = args->value->data;
+ value->len = args->value->len;
+ }
+ /* Regardless of what we changed, we're done editing the
+ list now that we've acted on the property we found. */
break;
}
+ /* Squirrel away a pointer to this property name/value pair, as
+ we may need this in the next iteration of this loop. */
+ prev = prop;
}
/* This property doesn't appear in the property list; add it to the
--
Yoshiki Hayashi
Received on Sat Oct 21 14:36:25 2006