Index: trac/db/util.py
===================================================================
--- trac/db/util.py	(revision 8666)
+++ trac/db/util.py	(working copy)
@@ -15,6 +15,66 @@
 #
 # Author: Christopher Lenz <cmlenz@gmx.de>
 
+def with_transaction(env, db, raise_exceptions = False):
+    """
+    Decorator for simple use-once transactions.
+    Usage:
+    -- def api_method(p1, p2):
+    --     @with_db_transaction(env, db)
+    --     def implementation_method(cursor):
+    --         # implementation
+    --         return result
+    --
+    --     result = implementation
+    """
+    def transaction_wrapper(fn):
+        if db:
+            try: return fn(db.cursor())
+            except Exception, e:
+                if raise_exceptions: raise
+        else:
+            dbtmp = env.get_db_cnx()
+            try:
+                r = fn(dbtmp.cursor())
+                dbtmp.commit()
+                return r
+            except Exception, e:
+                dbtmp.rollback()
+                if raise_exceptions: raise
+    return transaction_wrapper
+
+def with_db_transaction(env, db, raise_exceptions = False):
+    """
+    Transaction decorator for more complicated code,
+    that needs access to the connection itself,
+    either for helper methods or to pass it along.
+
+    Decorator for simple use-once transactions.
+    Usage:
+    -- def api_method(p1, p2):
+    --     @with_transaction(env, db)
+    --     def implementation_method(db):
+    --         # implementation
+    --         return result
+    --
+    --     result = implementation
+    """
+    def transaction_wrapper(fn):
+        if db:
+            try: return fn(db)
+            except Exception, e:
+                if raise_exceptions: raise
+        else:
+            dbtmp = env.get_db_cnx()
+            try:
+                r = fn(dbtmp)
+                dbtmp.commit()
+                return r
+            except Exception, e:
+                dbtmp.rollback()
+                if raise_exceptions: raise
+    return transaction_wrapper
+
 def sql_escape_percent(sql):
     import re
     return re.sub("'((?:[^']|(?:''))*)'",
