* rev-table.c (svn_fs__get_rev): Take trail as argument.
  All callers are changed.
* rev-table.c (svn_fs__put_rev): Ditto.
* rev-table.h (svn_fs__get_rev): Ditto.
* rev-table.h (svn_fs__put_rev): Ditto.
* rev-table.c (txn_body_revision_prop): New helper function
  for svn_fs_revision_prop.
* rev-table.c (svn_fs_revision_prop): New function
* rev-table.c (txn_body_revision_proplist): New helper
  function for svn_fs_revision_prop.
* rev-table.c (svn_fs_revision_proplist): New function.
* rev-table.c (txn_body_change_rev_prop): New helper
  function for svn_fs_change_rev_prop.
* rev-table.c (svn_fs_change_rev_prop): New function.
* skel.c (svn_fs__atom_matches_string): New function.
* skel.h (svn_fs__atom_matches_string): New function declaration.
Index: dag.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/dag.c,v
retrieving revision 1.62
diff -u -r1.62 dag.c
--- dag.c	2001/02/28 23:22:34	1.62
+++ dag.c	2001/03/01 07:48:22
@@ -301,8 +301,7 @@
                               svn_fs__parse_skel (rev_skel,
                                                   sizeof (rev_skel) - 1,
                                                   trail->pool),
-                              trail->db_txn,
-                              trail->pool));
+                              trail));
 
     if (rev != 0)
       return svn_error_createf (SVN_ERR_FS_CORRUPT, 0, 0, fs->pool,
Index: rev-table.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/rev-table.c,v
retrieving revision 1.6
diff -u -r1.6 rev-table.c
--- rev-table.c	2001/02/28 15:46:15	1.6
+++ rev-table.c	2001/03/01 07:48:23
@@ -69,8 +69,7 @@
 svn_fs__get_rev (skel_t **skel_p,
                  svn_fs_t *fs,
                  svn_revnum_t rev,
-                 DB_TXN *db_txn,
-                 apr_pool_t *pool)
+                 trail_t *trail)
 {
   int db_err;
   DBT key, value;
@@ -81,11 +80,11 @@
      numbers begin with one.  */
   db_recno_t recno = rev + 1;
 
-  db_err = fs->revisions->get (fs->revisions, db_txn,
+  db_err = fs->revisions->get (fs->revisions, trail->db_txn,
                                svn_fs__set_dbt (&key, &recno, sizeof (recno)),
                                svn_fs__result_dbt (&value),
                                0);
-  svn_fs__track_dbt (&value, pool);
+  svn_fs__track_dbt (&value, trail->pool);
 
   /* If there's no such revision, return an appropriately specific error.  */
   if (db_err == DB_NOTFOUND)
@@ -95,7 +94,7 @@
   SVN_ERR (DB_WRAP (fs, "reading filesystem revision", db_err));
 
   /* Parse and check the REVISION skel.  */
-  skel = svn_fs__parse_skel (value.data, value.size, pool);
+  skel = svn_fs__parse_skel (value.data, value.size, trail->pool);
   if (! skel
       || ! is_valid_filesystem_revision (skel))
     return svn_fs__err_corrupt_fs_revision (fs, rev);
@@ -109,8 +108,7 @@
 svn_fs__put_rev (svn_revnum_t *rev,
                  svn_fs_t *fs,
                  skel_t *skel,
-                 DB_TXN *db_txn,
-                 apr_pool_t *pool)
+                 trail_t *trail)
 {
   int db_err;
   DBT key, value;
@@ -120,9 +118,9 @@
   if (! is_valid_filesystem_revision (skel))
     return svn_fs__err_corrupt_fs_revision (fs, -1);
 
-  db_err = fs->revisions->put (fs->revisions, db_txn,
+  db_err = fs->revisions->put (fs->revisions, trail->db_txn,
                                svn_fs__recno_dbt(&key, &recno),
-                               svn_fs__skel_to_dbt (&value, skel, pool),
+                               svn_fs__skel_to_dbt (&value, skel, trail->pool),
                                DB_APPEND);
   SVN_ERR (DB_WRAP (fs, "storing filesystem revision", db_err));
 
@@ -143,8 +141,7 @@
   skel_t *skel;
   svn_fs_id_t *id;
 
-  SVN_ERR (svn_fs__get_rev (&skel, fs, rev,
-                            trail->db_txn, trail->pool));
+  SVN_ERR (svn_fs__get_rev (&skel, fs, rev, trail));
 
   id = svn_fs_parse_id (skel->children->next->data,
                         skel->children->next->len,
@@ -233,6 +230,235 @@
   SVN_ERR (svn_fs__retry_txn (fs, txn_body_youngest_rev, &args, pool));
 
   *youngest_p = youngest;
+  return SVN_NO_ERROR;
+}
+
+
+
+/* Generic revision operations.  */
+
+
+struct revision_prop_args {
+  svn_string_t **value_p;
+  svn_fs_t *fs;
+  svn_revnum_t rev;
+  svn_string_t *propname;
+};
+
+
+static svn_error_t *
+txn_body_revision_prop (void *baton,
+                        trail_t *trail)
+{
+  struct revision_prop_args *args = baton;
+
+  skel_t *skel;
+  skel_t *proplist, *prop;
+
+  SVN_ERR (svn_fs__get_rev (&skel, args->fs, args->rev, trail));
+  /* PROPLIST is the third element of revision skel.  */
+  proplist = skel->children->next->next;
+
+  /* Search the proplist for a property with the right name.  */
+  for (prop = proplist->children; prop; prop = prop->next->next)
+    {
+      skel_t *name = prop;
+      skel_t *value = prop->next;
+
+      if (svn_fs__atom_matches_string (name, args->propname))
+        {
+          *(args->value_p) = svn_string_ncreate (value->data, value->len,
+                                                 trail->pool);
+          return SVN_NO_ERROR;
+        }
+    }
+
+  *(args->value_p) = 0;
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_fs_revision_prop (svn_string_t **value_p,
+                      svn_fs_t *fs,
+                      svn_revnum_t rev,
+                      svn_string_t *propname,
+                      apr_pool_t *pool)
+{
+  struct revision_prop_args args;
+  svn_string_t *value;
+
+  args.value_p = &value;
+  args.fs = fs;
+  args.rev = rev;
+  args.propname = propname;
+  SVN_ERR (svn_fs__retry_txn (fs, txn_body_revision_prop, &args, pool));
+
+  *value_p = value;
+  return SVN_NO_ERROR;
+}
+
+
+struct revision_proplist_args {
+  apr_hash_t **table_p;
+  svn_fs_t *fs;
+  svn_revnum_t rev;
+};
+
+
+static svn_error_t *
+txn_body_revision_proplist (void *baton, trail_t *trail)
+{
+  struct revision_proplist_args *args = baton;
+
+  skel_t *skel;
+  skel_t *proplist, *prop;
+  apr_hash_t *table;
+
+  SVN_ERR (svn_fs__get_rev (&skel, args->fs, args->rev, trail));
+  /* PROPLIST is the third element of revision skel.  */
+  proplist = skel->children->next->next;
+
+  /* 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_revision_proplist (apr_hash_t **table_p,
+                          svn_fs_t *fs,
+                          svn_revnum_t rev,
+                          apr_pool_t *pool)
+{
+  struct revision_proplist_args args;
+  apr_hash_t *table;
+
+  args.table_p = &table;
+  args.fs = fs;
+  args.rev = rev;
+  SVN_ERR (svn_fs__retry_txn (fs, txn_body_revision_proplist, &args, pool));
+
+  *table_p = table;
+  return SVN_NO_ERROR;
+}
+
+
+struct change_rev_prop_args {
+  svn_fs_t *fs;
+  svn_revnum_t rev;
+  svn_string_t *name;
+  svn_string_t *value;
+};
+
+
+static svn_error_t *
+txn_body_change_rev_prop (void *baton, trail_t *trail)
+{
+  struct change_rev_prop_args *args = baton;
+
+  svn_fs_t *fs = args->fs;
+  skel_t *skel;
+  skel_t *proplist, *prop;
+  skel_t *prev = NULL;
+
+  SVN_ERR (svn_fs__get_rev (&skel, fs, args->rev, trail));
+  /* PROPLIST is the third element of revision skel.  */
+  proplist = skel->children->next->next;
+
+  /* Delete the skel, either replacing or adding the given property.  */
+  for (prop = proplist->children; prop; prop = prop->next->next)
+    {
+      skel_t *name = prop;
+      skel_t *value = prop->next;
+
+      if (svn_fs__atom_matches_string (name, args->name))
+        {
+
+          /* If VALUE is zero, remove this property altogether.  */
+          if (! args->value)
+            {
+              if (prev)
+                {
+                  if (prop->next)
+                    prev->next->next = prop->next->next;
+                  else
+                    prev->next->next = 0;
+                }
+              else
+                {
+                  if (prop->next)
+                    proplist->children = prop->next->next;
+                  else
+                    proplist->children = 0;
+                }
+            }
+          else
+            {
+              value->data = args->value->data;
+              value->len = args->value->len;
+            }
+
+          break;
+        }
+
+      prev = prop;
+    }
+
+  /* This property doesn't appear in the property list; add it to the
+     beginning.  */
+  if (! prop)
+    {
+      svn_fs__prepend (svn_fs__mem_atom (args->value->data,
+                                         args->value->len,
+                                         trail->pool),
+                       proplist);
+      svn_fs__prepend (svn_fs__mem_atom (args->name->data,
+                                         args->name->len,
+                                         trail->pool),
+                       proplist);
+    }
+
+  {
+    int db_err;
+    DBT key, value;
+    db_recno_t recno = args->rev + 1;
+    db_err = fs->revisions->put (fs->revisions, trail->db_txn,
+                                 svn_fs__set_dbt (&key, &recno, sizeof (recno)),
+                                 svn_fs__skel_to_dbt (&value, skel, trail->pool),
+                                 0);
+    SVN_ERR (DB_WRAP (fs, "updating filesystem revision", db_err));
+  }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_fs_change_rev_prop (svn_fs_t *fs,
+                        svn_revnum_t rev,
+                        svn_string_t *name,
+                        svn_string_t *value,
+                        apr_pool_t *pool)
+{
+  struct change_rev_prop_args args;
+
+  args.fs = fs;
+  args.rev = rev;
+  args.name = name;
+  args.value = value;
+  SVN_ERR (svn_fs__retry_txn (fs, txn_body_change_rev_prop, &args, pool));
+
   return SVN_NO_ERROR;
 }
 
Index: rev-table.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/rev-table.h,v
retrieving revision 1.4
diff -u -r1.4 rev-table.h
--- rev-table.h	2001/02/19 20:27:01	1.4
+++ rev-table.h	2001/03/01 07:48:23
@@ -35,26 +35,24 @@
 
 
 /* Set *SKEL_P to point to the REVISION skel for the filesystem
-   revision REV in FS, as part of the Berkeley DB transaction DB_TXN.
-   Allocate the skel and the data it points into in POOL.
+   revision REV in FS, as part of TRAIL.
+   Allocate the skel and the data it points into in TAIL->pool.
 
    This verifies that *SKEL_P is a well-formed REVISION skel.  */
 svn_error_t *svn_fs__get_rev (skel_t **skel_p,
                               svn_fs_t *fs,
                               svn_revnum_t rev,
-                              DB_TXN *db_txn,
-                              apr_pool_t *pool);
+                              trail_t *trail);
 
-/* Store SKEL as the REVISION skel in FS as part of the Berkeley DB
-   transaction DB_TXN, and return the new filesystem revision number
-   in *REV.  Do any necessary temporary allocation in POOL.
+/* Store SKEL as the REVISION skel in FS as part of TRAIL, and return
+   the new filesystem revision number in *REV.  Do any necessary
+   temporary allocation in TRAIL->pool.
 
    This verifies that SKEL is a well-formed REVISION skel.  */
 svn_error_t *svn_fs__put_rev (svn_revnum_t *rev,
                               svn_fs_t *fs,
                               skel_t *skel,
-                              DB_TXN *db_txn,
-                              apr_pool_t *pool);
+                              trail_t *trail);
 
 
 /* Set *ROOT_ID_P to the ID of the root directory of revision REV in FS,
Index: skel.c
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/skel.c,v
retrieving revision 1.20
diff -u -r1.20 skel.c
--- skel.c	2001/02/22 19:00:27	1.20
+++ skel.c	2001/03/01 07:48:23
@@ -524,6 +524,20 @@
 
 
 int
+svn_fs__atom_matches_string (skel_t *skel, svn_string_t *str)
+{
+  if (skel
+      && skel->is_atom)
+    {
+      return (skel->len == str->len
+              && ! memcmp (skel->data, str->data, skel->len));
+    }
+  else
+    return 0;
+}
+
+
+int
 svn_fs__list_length (skel_t *skel)
 {
   if (! skel
Index: skel.h
===================================================================
RCS file: /cvs/subversion/subversion/libsvn_fs/skel.h,v
retrieving revision 1.15
diff -u -r1.15 skel.h
--- skel.h	2001/02/21 23:26:20	1.15
+++ skel.h	2001/03/01 07:48:23
@@ -143,6 +143,10 @@
 int svn_fs__matches_atom (skel_t *skel, const char *str);
 
 
+/* Return true iff SKEL is an atom whose data is the same as STR.  */
+int svn_fs__atom_matches_string (skel_t *skel, svn_string_t *str);
+
+
 /* Return the length of the list skel SKEL.  Atoms have a length of -1.  */
 int svn_fs__list_length (skel_t *skel);
 
-- 
Yoshiki Hayashi
Received on Sat Oct 21 14:36:23 2006