You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/05/16 22:32:54 UTC
svn commit: r1339349 [2/37] - in /subversion/branches/fix-rdump-editor: ./
build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/ notes/ notes/api-errata...
Modified: subversion/branches/fix-rdump-editor/notes/directory-index/dirindex.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/directory-index/dirindex.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/directory-index/dirindex.py (original)
+++ subversion/branches/fix-rdump-editor/notes/directory-index/dirindex.py Wed May 16 20:32:43 2012
@@ -23,10 +23,64 @@ import sqlite3
class Error(Exception):
- pass
+ def __init__(self, msg, *args, **kwargs):
+ opcode = kwargs.pop("action", None)
+ if opcode is not None:
+ msg = Dirent._opname(opcode) + msg
+ super(Error, self).__init__(msg, *args, **kwargs)
+
+
+class SQL(object):
+ """Named index of SQL schema definitions and statements.
+
+ Parses "schema.sql" and creates a class-level attribute for each
+ script and statement in that file.
+ """
+
+ @classmethod
+ def _load_statements(cls):
+ import cStringIO
+ import pkgutil
+ import re
+
+ comment_rx = re.compile(r"\s*--.*$")
+ header_rx = re.compile(r"^---(STATEMENT|SCRIPT)"
+ r"\s+(?P<name>[_A-Z]+)$")
+
+ name = None
+ content = None
+
+ def record_current_statement():
+ if name is not None:
+ setattr(cls, name, content.getvalue())
+
+ schema = cStringIO.StringIO(pkgutil.get_data(__name__, "schema.sql"))
+ for line in schema:
+ line = line.rstrip()
+ if not line:
+ continue
+
+ header = header_rx.match(line)
+ if header:
+ record_current_statement()
+ name = header.group("name")
+ content = cStringIO.StringIO()
+ continue
+
+ line = comment_rx.sub("", line)
+ if not line:
+ continue
+
+ if content is not None:
+ content.write(line)
+ content.write("\n")
+ record_current_statement()
+SQL._load_statements()
class SQLobject(object):
+ """Base for ORM abstractions."""
+
__slots__ = ()
def __init__(self, **kwargs):
for name, val in kwargs.items():
@@ -68,91 +122,105 @@ class SQLobject(object):
class Revent(SQLobject):
+ """O/R mapping for the "revision" table."""
+
__slots__ = ("version", "created", "author", "log")
def _put(self, cursor):
if self.created is None:
now = datetime.datetime.utcnow()
self.created = now.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
- self._execute(cursor,
- "INSERT INTO revision (version, created, author, log)"
- " VALUES (?, ?, ?, ?)",
+ self._execute(cursor, SQL.INSERT_REVISION_RECORD,
[self.version, self.created, self.author, self.log])
@classmethod
def _get(cls, cursor, pkey):
- cursor.execute("SELECT * FROM revision WHERE version = ?", [pkey])
+ cursor.execute(SQL.GET_REVENT_BY_VERSION, [pkey])
return cls._from_row(cursor.fetchone())
-class Pathent(SQLobject):
- __slots__ = ("pathid", "abspath")
+class Strent(SQLobject):
+ """O/R mapping for the "strindex" table."""
+
+ __slots__ = ("strid", "content")
def _put(self, cursor):
- self._execute(cursor,
- "INSERT INTO pathindex (abspath) VALUES (?)",
- [self.abspath])
- self.pathid = cursor.lastrowid
+ self._execute(cursor, SQL.INSERT_STRINDEX_RECORD, [self.content])
+ self.strid = cursor.lastrowid
@classmethod
def _get(cls, cursor, pkey):
- cls._execute(cursor,
- "SELECT * FROM pathindex WHERE pathid = ?",
- [pkey])
+ cls._execute(cursor, SQL.GET_STRENT_BY_STRID, [pkey])
return cls._from_row(cursor.fetchone())
@classmethod
- def _find(cls, cursor, abspath):
- cls._execute(cursor,
- "SELECT * FROM pathindex WHERE abspath = ?",
- [abspath])
+ def _find(cls, cursor, content):
+ cls._execute(cursor, SQL.GET_STRENT_BY_CONTENT, [content])
return cls._from_row(cursor.fetchone())
class Dirent(SQLobject):
- __slots__ = ("rowid", "pathid", "version", "deleted",
- "kind", "origin", "copied", "subtree",
+ """O/R mapping for a virtual non-materialized view representing
+ a join of the "dirindex" and "strindex" tables."""
+
+ __slots__ = ("rowid", "origin", "pathid", "version",
+ "kind", "opcode", "subtree",
"abspath")
+ # Kinds
+ DIR = "D"
+ FILE = "F"
+
+ # Opcodes
+ ADD = "A"
+ REPLACE = "R"
+ MODIFY = "M"
+ DELETE = "D"
+ RENAME = "N"
+
+ # Opcode names
+ __opnames = {ADD: "add",
+ REPLACE: "replace",
+ MODIFY: "modify",
+ DELETE: "delete",
+ RENAME: "rename"}
+
+ @classmethod
+ def _opname(cls, opcode):
+ return cls.__opnames.get(opcode)
+
+ @property
+ def _deleted(self):
+ return (self.opcode == self.DELETE)
+
def __str__(self):
- return "%3d %c%c %s" % (
+ return "%d %c%c%c %c %s" % (
self.version,
- self.deleted and "x" or " ",
- self.kind and "f" or "d",
- self.abspath)
+ self.subtree and "(" or " ",
+ self.opcode,
+ self.subtree and ")" or " ",
+ self.kind, self.abspath)
def _put(self, cursor):
- pathent = Pathent._find(cursor, self.abspath)
- if pathent is None:
- pathent = Pathent(abspath = self.abspath)
- pathent._put(cursor)
- self._execute(cursor,
- "INSERT INTO dirindex"
- " (pathid, version, deleted,"
- " kind, origin, copied, subtree)"
- " VALUES (?, ?, ?, ?, ?, ?, ?)",
- [pathent.pathid, self.version, self.deleted,
- self.kind, self.origin, self.copied, self.subtree])
+ strent = Strent._find(cursor, self.abspath)
+ if strent is None:
+ strent = Strent(content = self.abspath)
+ strent._put(cursor)
+ self._execute(cursor, SQL.INSERT_DIRINDEX_RECORD,
+ [self.origin, strent.strid, self.version,
+ self.kind, self.opcode,self.subtree])
self.rowid = cursor.lastrowid
- self.pathid = pathent.pathid
+ self.pathid = strent.strid
@classmethod
def _get(cls, cursor, pkey):
- cls._execute(cursor,
- "SELECT dirindex.*, pathindex.abspath"
- " FROM dirindex JOIN pathindex"
- " ON dirindex.pathid = pathindex.pathid"
- " WHERE dirindex.rowid = ?", [pkey])
+ cls._execute(cursor, SQL.GET_DIRENT_BY_ROWID, [pkey])
return cls._from_row(cursor.fetchone())
@classmethod
def _find(cls, cursor, abspath, version):
cls._execute(cursor,
- "SELECT dirindex.*, pathindex.abspath"
- " FROM dirindex JOIN pathindex"
- " ON dirindex.pathid = pathindex.pathid"
- " WHERE pathindex.abspath = ?"
- " AND dirindex.version = ?",
+ SQL.GET_DIRENT_BY_ABSPATH_AND_VERSION,
[abspath, version])
return cls._from_row(cursor.fetchone())
@@ -162,53 +230,27 @@ class Index(object):
self.conn = sqlite3.connect(database, isolation_level = "IMMEDIATE")
self.conn.row_factory = sqlite3.Row
self.cursor = self.conn.cursor()
+ self.cursor.execute("PRAGMA page_size = 4096")
+ self.cursor.execute("PRAGMA temp_store = MEMORY")
self.cursor.execute("PRAGMA foreign_keys = ON")
self.cursor.execute("PRAGMA case_sensitive_like = ON")
self.cursor.execute("PRAGMA encoding = 'UTF-8'")
- __schema = """
-DROP TABLE IF EXISTS dirindex;
-DROP TABLE IF EXISTS pathindex;
-DROP TABLE IF EXISTS revision;
-
-CREATE TABLE revision (
- version integer NOT NULL PRIMARY KEY,
- created timestamp NOT NULL,
- author varchar NULL,
- log varchar NULL
-);
-
-CREATE TABLE pathindex (
- pathid integer NOT NULL PRIMARY KEY,
- abspath varchar NOT NULL UNIQUE
-);
-
-CREATE TABLE dirindex (
- rowid integer NOT NULL PRIMARY KEY,
- pathid integer NOT NULL REFERENCES pathindex(pathid),
- version integer NOT NULL REFERENCES revision(version),
- deleted boolean NOT NULL,
- kind integer NOT NULL,
- origin integer NULL REFERENCES dirindex(rowid),
- copied boolean NOT NULL,
- subtree boolean NOT NULL
-);
-CREATE UNIQUE INDEX dirindex_versioned_tree ON dirindex(pathid, version DESC);
-CREATE INDEX dirindex_successor_list ON dirindex(origin);
-CREATE INDEX dirindex_deleted ON dirindex(deleted);
-
-INSERT INTO revision (version, created, author, log)
- VALUES (0, 'EPOCH', NULL, NULL);
-INSERT INTO pathindex (pathid, abspath) VALUES (0, '/');
-INSERT INTO dirindex (rowid, pathid, version, deleted,
- kind, origin, copied, subtree)
- VALUES (0, 0, 0, 0, 0, NULL, 0, 0);
-"""
+ @staticmethod
+ def normpath(abspath):
+ return abspath.rstrip("/")
+
+ @staticmethod
+ def subtree_pattern(abspath):
+ return (abspath.rstrip("/")
+ .replace("#", "##")
+ .replace("%", "#%")
+ .replace("_", "#_")) + "/%"
def initialize(self):
try:
- SQLobject._log("%s", self.__schema)
- self.cursor.executescript(self.__schema)
+ SQLobject._log("%s", SQL.CREATE_SCHEMA)
+ self.cursor.executescript(SQL.CREATE_SCHEMA)
self.commit()
finally:
self.rollback()
@@ -245,34 +287,20 @@ INSERT INTO dirindex (rowid, pathid, ver
def lookup(self, abspath, version):
SQLobject._execute(
self.cursor,
- "SELECT dirindex.*, pathindex.abspath FROM dirindex"
- " JOIN pathindex ON dirindex.pathid = pathindex.pathid"
- " WHERE pathindex.abspath = ? AND dirindex.version <= ?"
- " ORDER BY pathindex.abspath ASC, dirindex.version DESC"
- " LIMIT 1",
+ SQL.LOOKUP_ABSPATH_AT_REVISION,
[abspath, version])
row = self.cursor.fetchone()
- if row is not None and not row["deleted"]:
- return Dirent._from_row(row)
+ if row is not None:
+ dirent = Dirent._from_row(row)
+ if not dirent._deleted:
+ return dirent
return None
def subtree(self, abspath, version):
- pattern = (abspath.rstrip("/")
- .replace("#", "##")
- .replace("%", "#%")
- .replace("_", "#_")) + "/%"
SQLobject._execute(
self.cursor,
- "SELECT dirindex.*, pathindex.abspath FROM dirindex"
- " JOIN pathindex ON dirindex.pathid = pathindex.pathid"
- " JOIN (SELECT pathid, MAX(version) AS maxver FROM dirindex"
- " WHERE version <= ? GROUP BY pathid) AS filtered"
- " ON dirindex.pathid == filtered.pathid"
- " AND dirindex.version == filtered.maxver"
- " WHERE pathindex.abspath LIKE ? ESCAPE '#'"
- " AND NOT dirindex.deleted"
- " ORDER BY pathindex.abspath ASC",
- [version, pattern])
+ SQL.LIST_SUBTREE_AT_REVISION,
+ [version, self.subtree_pattern(abspath)])
for row in self.cursor:
yield Dirent._from_row(row)
@@ -286,10 +314,7 @@ INSERT INTO dirindex (rowid, pathid, ver
assert isinstance(dirent, Dirent)
SQLobject._execute(
self.cursor,
- "SELECT dirindex.*, pathindex.abspath FROM dirindex"
- " JOIN pathindex ON dirindex.pathid = pathindex.pathid"
- " WHERE dirindex.origin = ?"
- " ORDER BY pathindex.abspath ASC, dirindex.version ASC",
+ SQL.LIST_DIRENT_SUCCESSORS,
[dirent.rowid])
for row in self.cursor:
yield Dirent._from_row(row)
@@ -307,157 +332,218 @@ class Revision(object):
self.__context = None
index.rollback()
+ class __Context(object):
+ def __init__(self, version, connection):
+ self.version = version
+ self.conn = connection
+ self.cursor = connection.cursor()
+ SQLobject._execute(self.cursor, SQL.CREATE_TRANSACTION_CONTEXT)
+
+ def clear(self):
+ SQLobject._execute(self.cursor, SQL.REMOVE_TRANSACTION_CONTEXT)
+
+ def __iter__(self):
+ SQLobject._execute(self.cursor, SQL.LIST_TRANSACTION_RECORDS)
+ for row in self.cursor:
+ dirent = Dirent._from_row(row)
+ dirent.version = self.version
+ yield dirent
+
+ def lookup(self, abspath):
+ SQLobject._execute(self.cursor,
+ SQL.GET_TRANSACTION_RECORD,
+ [abspath])
+ row = self.cursor.fetchone()
+ if row is not None:
+ dirent = Dirent._from_row(row)
+ dirent.version = self.version
+ return dirent
+ return None
+
+ def remove(self, abspath, purge=False):
+ target = self.lookup(abspath)
+ if not target:
+ raise Error("txn context: remove nonexistent " + abspath)
+ logging.debug("txn context: remove %s", abspath)
+ SQLobject._execute(self.cursor,
+ SQL.REMOVE_TRANSACTION_RECORD,
+ [abspath])
+ if purge:
+ logging.debug("txn context: purge %s/*", abspath)
+ SQLobject._execute(self.cursor,
+ SQL.REMOVE_TRANSACTION_SUBTREE,
+ [Index.subtree_pattern(abspath)])
+
+ def record(self, dirent, replace=False, purge=False):
+ target = self.lookup(dirent.abspath)
+ if target is not None:
+ if not replace:
+ raise Error("txn context: record existing "
+ + dirent.abspath)
+ elif not target.subtree:
+ raise Error("txn context: replace conflict "
+ + dirent.abspath)
+ self.remove(target.abspath, purge and target.kind == Dirent.DIR)
+ SQLobject._execute(self.cursor,
+ SQL.INSERT_TRANSACTION_RECORD,
+ [dirent.origin, dirent.abspath,
+ dirent.kind, dirent.opcode, dirent.subtree])
+
def __enter__(self):
if self.revent is not None:
raise Error("revision is read-only")
- SQLobject._log("BEGIN")
+ self.__context = self.__Context(self.version, self.index.conn)
+ SQLobject._execute(self.index.cursor, "BEGIN")
self.revent = self.index.new_revision(
self.version, self.__created, self.__author, self.__log)
- self.__context = {}
return self
def __exit__(self, exc_type, exc_value, traceback):
try:
- if exc_type is None and len(self.__context):
- for dirent in sorted(self.__context.itervalues()):
+ if exc_type is None:
+ for dirent in self.__context:
self.index.insert(dirent)
+ logging.debug("insert: %s", dirent)
self.index.commit()
+ else:
+ self.index.rollback()
except:
self.index.rollback()
raise
finally:
+ self.__context.clear()
self.__context = None
- def __record(self, dirent, action):
- self.__context[dirent.abspath] = dirent
- if dirent.subtree:
- action = "(%s)" % action
- else:
- action = " %s " % action
- logging.debug(" %-9s %s", action, dirent)
+ def __record(self, dirent, replace=False, purge=False):
+ self.__context.record(dirent, replace, purge)
+ logging.debug("record: %s", dirent)
- def __check_writable(self, action):
+ def __check_writable(self, opcode):
if self.__context is None:
- raise Error(action + " requires a transaction")
+ raise Error(" requires a transaction", action=opcode)
- def __check_not_root(self, abspath, action):
+ def __check_not_root(self, abspath, opcode):
if abspath.rstrip("/") == "":
- raise Error(action + " not allowed on /")
+ raise Error(" not allowed on /", action=opcode)
- def __find_target(self, abspath, action):
- target = self.__context.get(abspath)
- if target is not None and not target.subtree:
- raise Error(action + " overrides explicit " + abspath)
- if target is None:
- target = self.index.lookup(abspath, self.version - 1)
+ def __find_target(self, abspath, opcode):
+ target = self.__context.lookup(abspath)
+ if target is not None:
+ if not target.subtree:
+ raise Error(" overrides explicit " + abspath, action=opcode)
+ return target, target.origin
+ target = self.index.lookup(abspath, self.version - 1)
if target is None:
- raise Error(action + " target does not exist: " + abspath)
- return target
+ raise Error(" target does not exist: " + abspath, action=opcode)
+ return target, target.rowid
def lookup(self, abspath):
try:
- return self.index.lookup(abspath, self.version)
+ return self.index.lookup(self.index.normpath(abspath),
+ self.version)
finally:
if self.__context is None:
self.index.rollback()
- def __add(self, action, abspath, kind, frompath, fromver):
+ def __add(self, opcode, abspath, kind, frompath, fromver):
origin = None
if frompath is not None:
+ frompath = self.index.normpath(frompath)
+ fromver = int(fromver)
origin = self.index.lookup(frompath, fromver)
if origin is None:
- raise Error(action + " source does not exist: " + frompath)
+ raise Error(" source does not exist: " + frompath, action=opcode)
if origin.kind != kind:
- raise Error(action + " changes the source object kind")
+ raise Error(" changes the source object kind", action=opcode)
origin = origin.rowid
- dirent = Dirent(abspath = abspath,
+ dirent = Dirent(origin = origin,
+ abspath = abspath,
version = self.version,
- deleted = 0,
kind = kind,
- origin = origin,
- copied = int(origin is not None),
+ opcode = opcode,
subtree = 0)
- self.__record(dirent, action)
- if frompath is not None:
- offset = len(frompath.rstrip("/"))
- prefix = abspath.rstrip("/")
- for source in self.index.subtree(frompath, fromver):
- dirent = Dirent(rowid = source.rowid,
- abspath = prefix + source.abspath[offset:],
- version = self.version,
- deleted = 0,
- kind = source.kind,
- origin = source.rowid,
- copied = 1,
- subtree = 1)
- self.__record(dirent, action)
+ self.__record(dirent,
+ replace=(opcode == Dirent.REPLACE),
+ purge=(opcode == Dirent.REPLACE))
+ if frompath is not None and dirent.kind == Dirent.DIR:
+ prefix = dirent.abspath
+ offset = len(frompath)
+ for source in list(self.index.subtree(frompath, fromver)):
+ abspath = prefix + source.abspath[offset:]
+ self.__record(Dirent(origin = source.rowid,
+ abspath = abspath,
+ version = self.version,
+ kind = source.kind,
+ opcode = opcode,
+ subtree = 1))
def add(self, abspath, kind, frompath=None, fromver=None):
- action = "add"
- self.__check_writable(action)
- self.__check_not_root(abspath, action)
- return self.__add(action, abspath, kind, frompath, fromver)
+ opcode = Dirent.ADD
+ abspath = self.index.normpath(abspath)
+ self.__check_writable(opcode)
+ self.__check_not_root(abspath, opcode)
+ return self.__add(opcode, abspath, kind, frompath, fromver)
def replace(self, abspath, kind, frompath=None, fromver=None):
- action = "replace"
- self.__check_writable(action)
- self.__check_not_root(abspath, action)
- self.__find_target(abspath, action)
- return self.__add(action, abspath, kind, frompath, fromver)
+ opcode = Dirent.REPLACE
+ abspath = self.index.normpath(abspath)
+ self.__check_writable(opcode)
+ self.__check_not_root(abspath, opcode)
+ self.__find_target(abspath, opcode)
+ return self.__add(opcode, abspath, kind, frompath, fromver)
def modify(self, abspath):
- action = "modify"
- self.__check_writable(action)
- target = self.__find_target(abspath, action)
- dirent = Dirent(abspath = abspath,
+ opcode = Dirent.MODIFY
+ abspath = self.index.normpath(abspath)
+ self.__check_writable(opcode)
+ target, origin = self.__find_target(abspath, opcode)
+ dirent = Dirent(origin = origin,
+ abspath = abspath,
version = self.version,
- deleted = 0,
kind = target.kind,
- origin = target.rowid,
- copied = 0,
+ opcode = opcode,
subtree = 0)
- self.__record(dirent, action)
+ self.__record(dirent, replace=True)
def delete(self, abspath):
- action = "replace"
- self.__check_writable(action)
- self.__check_not_root(abspath, action)
- target = self.__find_target(abspath, action)
- dirent = Dirent(abspath = abspath,
+ opcode = Dirent.DELETE
+ abspath = self.index.normpath(abspath)
+ self.__check_writable(opcode)
+ self.__check_not_root(abspath, opcode)
+ target, origin = self.__find_target(abspath, opcode)
+ dirent = Dirent(origin = origin,
+ abspath = abspath,
version = self.version,
- deleted = 1,
kind = target.kind,
- origin = target.rowid,
- copied = 0,
+ opcode = opcode,
subtree = 0)
- self.__record(dirent, action)
- for source in self.index.subtree(abspath, self.version - 1):
- dirent = Dirent(rowid = source.rowid,
- abspath = source.abspath,
- version = self.version,
- deleted = 1,
- kind = source.kind,
- origin = source.rowid,
- copied = 0,
- subtree = 1)
- self.__record(dirent, action)
+ self.__record(dirent, replace=True, purge=True)
+ if target.version < self.version and dirent.kind == Dirent.DIR:
+ for source in self.index.subtree(abspath, self.version - 1):
+ self.__record(Dirent(origin = source.rowid,
+ abspath = source.abspath,
+ version = self.version,
+ kind = source.kind,
+ opcode = opcode,
+ subtree = 1))
def simpletest(database):
ix = Index(database)
ix.initialize()
with Revision(ix, 1) as rev:
- rev.add(u'/A', 0)
- rev.add(u'/A/B', 0)
- rev.add(u'/A/B/c', 1)
+ rev.add(u'/A', Dirent.DIR)
+ rev.add(u'/A/B', Dirent.DIR)
+ rev.add(u'/A/B/c', Dirent.FILE)
with Revision(ix, 2) as rev:
- rev.add(u'/A/B/d', 1)
+ rev.add(u'/A/B/d', Dirent.FILE)
with Revision(ix, 3) as rev:
- rev.add(u'/X', 0, u'/A', 1)
- rev.add(u'/X/B/d', 1, u'/A/B/d', 2)
+ rev.add(u'/X', Dirent.DIR, u'/A', 1)
+ rev.add(u'/X/B/d', Dirent.FILE, u'/A/B/d', 2)
with Revision(ix, 4) as rev:
+ # rev.rename(u'/X/B/d', u'/X/B/x')
rev.delete(u'/X/B/d')
- rev.add(u'/X/B/x', 1, u'/X/B/d', 3)
+ rev.add(u'/X/B/x', Dirent.FILE, u'/X/B/d', 3)
with Revision(ix, 5) as rev:
rev.delete(u'/A')
@@ -474,12 +560,13 @@ def simpletest(database):
print "/A/B/c@4 -> %s@%d" % (dirent.abspath, dirent.version)
for succ in ix.successors(dirent):
print "%11s %s %s@%d" % (
- "", succ.deleted and "x_x" or "-->",
+ "", succ._deleted and "x_x" or "-->",
succ.abspath, succ.version)
ix.close()
def loggedsimpletest(database):
import sys
- logging.basicConfig(level=SQLobject.LOGLEVEL, stream=sys.stderr)
+ logging.basicConfig(level=logging.DEBUG, #SQLobject.LOGLEVEL,
+ stream=sys.stderr)
simpletest(database)
Modified: subversion/branches/fix-rdump-editor/notes/directory-index/logimport.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/directory-index/logimport.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/directory-index/logimport.py (original)
+++ subversion/branches/fix-rdump-editor/notes/directory-index/logimport.py Wed May 16 20:32:43 2012
@@ -16,7 +16,11 @@
# specific language governing permissions and limitations
# under the License.
-# Usage: logimport <database-name> <repoa-url> [path-to-svn]
+# Usage: logimport [options] <database-name> <repoa-url>
+# Options:
+# --svn=PATH Use a non-default svn binary
+# --debug Enable debug-level logging to logimport.debug.log
+# --sqldebug Enable SQL-level logging to logimport.sql.log
#
# Converts the history of the repository at <repos-url> into a
# single-tree directory index.
@@ -31,11 +35,11 @@ try:
except ImportError:
from xml.etree.ElementTree import iterparse
-from dirindex import Index, Revision
+from dirindex import Dirent, Index, Revision
def parse(index, stream):
- kindmap = {"dir": 0, "file": 1}
+ kindmap = {"dir": Dirent.DIR, "file": Dirent.FILE}
version = None
revcount = 0
@@ -46,11 +50,11 @@ def parse(index, stream):
version = int(logentry.get("revision"))
revcount += 1
- if revcount == 1 or not revcount % 1000:
- revlogger = logging.info
+ if revcount == 1:
+ logging.info("initial: r%d", version)
else:
- revlogger = logging.debug
- revlogger("%d: r%d", revcount, version)
+ logger = not revcount % 1000 and logging.info or logging.debug
+ logger("%d: r%d", revcount, version)
created = logentry.find("date")
if created is not None:
@@ -77,7 +81,7 @@ def parse(index, stream):
action = path.get("action")
handler, newnode = actionmap[action]
if not newnode:
- logging.debug(" %-s %s", action, abspath)
+ logging.debug(" %s %s", action, abspath)
handler(abspath)
continue
@@ -98,24 +102,83 @@ def parse(index, stream):
def logimport(database, url, svn):
- index = Index(database)
- index.initialize()
- index.cursor.execute("PRAGMA journal_mode = MEMORY")
- index.cursor.execute("PRAGMA locking_mode = EXCLUSIVE")
- index.cursor.execute("PRAGMA synchronous = OFF")
- svnlog = subprocess.Popen(
- [svn, "log", "-v", "--xml", "-r1:HEAD", url],
- stdout = subprocess.PIPE)
- parse(index, svnlog.stdout)
- sys.exit(svnlog.wait())
+ try:
+ index = Index(database)
+ index.cursor.execute("PRAGMA journal_mode = MEMORY")
+ index.cursor.execute("PRAGMA locking_mode = EXCLUSIVE")
+ index.cursor.execute("PRAGMA synchronous = OFF")
+ index.cursor.execute("PRAGMA cache_size = -100000")
+ index.initialize()
+ svnlog = subprocess.Popen(
+ [svn, "log", "-v", "--xml", "-r1:HEAD", url],
+ stdout = subprocess.PIPE)
+ parse(index, svnlog.stdout)
+ return svnlog.wait()
+ except:
+ logging.exception("logimport failed")
+ try:
+ svnlog.wait()
+ except:
+ pass
+ return 2
+
+
+def main():
+ import logging.config
+ from optparse import OptionParser
+ from dirindex import SQLobject
+
+ parser = OptionParser("Usage: %prog [options] <database-name> <repoa-url>")
+ parser.add_option("--svn", action="store", default="svn",
+ help="Use a non-default svn binary", metavar="PATH")
+ parser.add_option("--debug", action="store_true", default=False,
+ help="Enable debug-level logging to logimport.debug.log")
+ parser.add_option("--sqldebug", action="store_true", default=False,
+ help="Enable SQL-level logging to logimport.debug.log")
+
+ opts, args = parser.parse_args()
+ if len(args) != 2:
+ parser.error("wrong number of arguments")
+ database, url = args
+
+ logconfig = {
+ "version": 1,
+ "formatters": {
+ "console": {"format": "%(levelname)-7s %(message)s"},
+ "logfile": {"format": "%(asctime)s %(levelname)-7s %(message)s"}},
+ "handlers": {
+ "console": {
+ "class": "logging.StreamHandler",
+ "level": logging.INFO,
+ "stream": sys.stderr,
+ "formatter": "console"}},
+ "root": {
+ "level": logging.INFO,
+ "handlers": ["console"]}}
+
+ handlers = logconfig["root"]["handlers"]
+ if opts.debug:
+ logconfig["root"]["level"] = logging.DEBUG
+ logconfig["handlers"]["debug"] = {
+ "class": "logging.FileHandler",
+ "level": logging.DEBUG,
+ "mode": "w",
+ "filename": "./logimport.debug.log",
+ "formatter": "logfile"}
+ handlers.append("debug")
+ if opts.sqldebug:
+ logconfig["root"]["level"] = SQLobject.LOGLEVEL
+ logconfig["handlers"]["sqldebug"] = {
+ "class": "logging.FileHandler",
+ "level": SQLobject.LOGLEVEL,
+ "mode": "w",
+ "filename": "./logimport.sql.log",
+ "formatter": "logfile"}
+ handlers.append("sqldebug")
+
+ logging.config.dictConfig(logconfig)
+ sys.exit(logimport(database, url, opts.svn))
if __name__ == "__main__":
- database = sys.argv[1]
- url = sys.argv[2]
- if len(sys.argv) > 3:
- svn = sys.argv[3]
- else:
- svn = "svn"
- logging.basicConfig(level=logging.INFO, stream=sys.stderr)
- logimport(database, url, svn)
+ main()
Modified: subversion/branches/fix-rdump-editor/notes/directory-index/schema.sql
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/directory-index/schema.sql?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/directory-index/schema.sql (original)
+++ subversion/branches/fix-rdump-editor/notes/directory-index/schema.sql Wed May 16 20:32:43 2012
@@ -16,6 +16,15 @@
-- specific language governing permissions and limitations
-- under the License.
+
+---SCRIPT CREATE_SCHEMA
+
+DROP TABLE IF EXISTS dirindex;
+DROP TABLE IF EXISTS strindex;
+DROP TABLE IF EXISTS revision;
+
+-- Revision record
+
CREATE TABLE revision (
version integer NOT NULL PRIMARY KEY,
created timestamp NOT NULL,
@@ -23,73 +32,152 @@ CREATE TABLE revision (
log varchar NULL
);
-CREATE TABLE pathindex (
- pathid integer NOT NULL PRIMARY KEY,
- abspath varchar NOT NULL UNIQUE
+-- Path lookup table
+
+CREATE TABLE strindex (
+ strid integer NOT NULL PRIMARY KEY,
+ content varchar NOT NULL UNIQUE
);
+-- Versioned directory tree
+
CREATE TABLE dirindex (
-- unique id of this node revision, used for
-- predecessor/successor links
rowid integer NOT NULL PRIMARY KEY,
+ -- link to this node's immediate predecessor
+ origin integer NULL REFERENCES dirindex(rowid),
+
-- absolute (repository) path
- pathid integer NOT NULL REFERENCES pathindex(pathid),
+ pathid integer NOT NULL REFERENCES strindex(strid),
-- revision number
version integer NOT NULL REFERENCES revision(version),
- -- node deletion flag
- deleted boolean NOT NULL,
-
- -- node kind (0 = dir, 1 = file, etc.)
- kind integer NOT NULL,
-
- -- predecessor link
- origin integer NULL REFERENCES dirindex(rowid),
+ -- node kind (D = dir, F = file, etc.)
+ kind character(1) NOT NULL,
- -- the predecessor is a copy source
- copied boolean NOT NULL,
+ -- the operation that produced this entry:
+ -- A = add, R = replace, M = modify, D = delete, N = rename
+ opcode character(1) NOT NULL,
-- the index entry is the result of an implicit subtree operation
subtree boolean NOT NULL
);
CREATE UNIQUE INDEX dirindex_versioned_tree ON dirindex(pathid, version DESC);
CREATE INDEX dirindex_successor_list ON dirindex(origin);
-CREATE INDEX dirindex_deleted ON dirindex(deleted);
+CREATE INDEX dirindex_operation ON dirindex(opcode);
+
+-- Repository root
--- repository root
INSERT INTO revision (version, created, author, log)
VALUES (0, 'EPOCH', NULL, NULL);
-INSERT INTO pathindex (pathid, abspath) VALUES (0, '/');
-INSERT INTO dirindex (rowid, pathid, version, deleted,
- kind, origin, copied, subtree)
- VALUES (0, 0, 0, 0, 0, NULL, 0, 0);
-
-
--- lookup PATH@REVISION
-
-SELECT
- dirindex.*, pathindex.abspath
-FROM dirindex JOIN pathindex
- ON dirindex.pathid = pathindex.pathid
-WHERE
- pathindex.abspath = '' -- $PATH
- AND dirindex.version <= 0 -- $REVISION
-ORDER BY pathindex.abspath ASC, dirindex.version DESC
-LIMIT 1; -- then check dirindex.deleted
-
--- single-revision tree for REVISION
-
-SELECT
- dirindex.*, pathindex.abspath
-FROM dirindex JOIN pathindex
- ON dirindex.pathid = pathindex.pathid
+INSERT INTO strindex (strid, content) VALUES (0, '/');
+INSERT INTO dirindex (rowid, origin, pathid, version, kind, opcode, subtree)
+ VALUES (0, NULL, 0, 0, 'D', 'A', 0);
+
+
+---STATEMENT INSERT_REVISION_RECORD
+
+INSERT INTO revision (version, created, author, log)
+ VALUES (?, ?, ?, ?);
+
+---STATEMENT GET_REVENT_BY_VERSION
+
+SELECT * FROM revision WHERE version = ?;
+
+---STATEMENT INSERT_STRINDEX_RECORD
+
+INSERT INTO strindex (content) VALUES (?);
+
+---STATEMENT GET_STRENT_BY_STRID
+
+SELECT * FROM strindex WHERE strid = ?;
+
+---STATEMENT GET_STRENT_BY_CONTENT
+
+SELECT * FROM strindex WHERE content = ?;
+
+---STATEMENT INSERT_DIRINDEX_RECORD
+
+INSERT INTO dirindex (origin, pathid, version, kind, opcode, subtree)
+ VALUES (?, ?, ?, ?, ?, ?);
+
+---STATEMENT GET_DIRENT_BY_ROWID
+
+SELECT dirindex.*, strindex.content FROM dirindex
+ JOIN strindex ON dirindex.pathid = strindex.strid
+WHERE dirindex.rowid = ?;
+
+---STATEMENT GET_DIRENT_BY_ABSPATH_AND_VERSION
+
+SELECT dirindex.*, strindex.content AS abspath FROM dirindex
+ JOIN strindex ON dirindex.pathid = strindex.strid
+WHERE abspath = ? AND dirindex.version = ?;
+
+---STATEMENT LOOKUP_ABSPATH_AT_REVISION
+
+SELECT dirindex.*, strindex.content AS abspath FROM dirindex
+ JOIN strindex ON dirindex.pathid = strindex.strid
+WHERE abspath = ? AND dirindex.version <= ?
+ORDER BY abspath ASC, dirindex.version DESC
+LIMIT 1;
+
+---STATEMENT LIST_SUBTREE_AT_REVISION
+
+SELECT dirindex.*, strindex.content AS abspath FROM dirindex
+ JOIN strindex ON dirindex.pathid = strindex.strid
JOIN (SELECT pathid, MAX(version) AS maxver FROM dirindex
- WHERE version <= 0 -- $REVISION
- GROUP BY pathid)
- AS filtered
+ WHERE version <= ? GROUP BY pathid)
+ AS filtered
ON dirindex.pathid == filtered.pathid
- AND dirindex.version == filtered.maxver
-WHERE NOT dirindex.deleted
-ORDER BY pathindex.abspath ASC;
+ AND dirindex.version == filtered.maxver
+WHERE abspath LIKE ? ESCAPE '#'
+ AND dirindex.opcode <> 'D'
+ORDER BY abspath ASC;
+
+---STATEMENT LIST_DIRENT_SUCCESSORS
+
+SELECT dirindex.*, strindex.content AS abspath FROM dirindex
+ JOIN strindex ON dirindex.pathid = strindex.strid
+WHERE dirindex.origin = ?
+ORDER BY abspath ASC, dirindex.version ASC;
+
+
+-- Temporary transaction
+
+---SCRIPT CREATE_TRANSACTION_CONTEXT
+
+CREATE TEMPORARY TABLE txncontext (
+ origin integer NULL,
+ abspath varchar NOT NULL UNIQUE,
+ kind character(1) NOT NULL,
+ opcode character(1) NOT NULL,
+ subtree boolean NOT NULL
+);
+
+---SCRIPT REMOVE_TRANSACTION_CONTEXT
+
+DROP TABLE IF EXISTS temp.txncontext;
+
+---STATEMENT INSERT_TRANSACTION_RECORD
+
+INSERT INTO temp.txncontext (origin, abspath, kind, opcode, subtree)
+ VALUES (?, ?, ?, ?, ?);
+
+---STATEMENT GET_TRANSACTION_RECORD
+
+SELECT * FROM temp.txncontext WHERE abspath = ?;
+
+---STATEMENT REMOVE_TRANSACTION_RECORD
+
+DELETE FROM temp.txncontext WHERE abspath = ?;
+
+---STATEMENT REMOVE_TRANSACTION_SUBTREE
+
+DELETE FROM temp.txncontext WHERE abspath LIKE ? ESCAPE '#';
+
+---STATEMENT LIST_TRANSACTION_RECORDS
+
+SELECT * FROM temp.txncontext ORDER BY abspath ASC;
Modified: subversion/branches/fix-rdump-editor/notes/knobs
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/knobs?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/knobs (original)
+++ subversion/branches/fix-rdump-editor/notes/knobs Wed May 16 20:32:43 2012
@@ -134,20 +134,23 @@ SVN_I_LIKE_LATENCY_SO_IGNORE_HTTPV2
3.6 SVN_FS_FS_MAX_LINEAR_DELTIFICATION
Scope: libsvn_fs_fs
- Purpose: max length + 1 of the linear deltification history
- before skip-deltification kicks in
+ Purpose: Controls the space efficiency vs. reconstruction costs tradeoff
+ of rep deltification. Defines the max length of the linear
+ deltification history before skip-deltification kicks in.
+ Values < 2 result in skip-delta-only behavior.
Default: 16
- Range: natural integers
- Suggested: 2, 4, 8, 16, 32, 64
+ Range: natural integers; should be a power of 2
+ Suggested: 1, 4, 8, 16, 32, 64
3.7 SVN_FS_FS_MAX_DELTIFICATION_WALK
Scope: libsvn_fs_fs
- Purpose: max skip deltification range. Change histories
- longer than that will be restarted with a fulltext.
+ Purpose: Limits the skip deltification range to provide commit runtime
+ guarantees. Change histories longer than that will be restarted
+ with a fulltext. Values < 1 disable deltification.
Default: 1023
- Range: natural integers
- Suggested: 1, 2, 3, 4, 5, 7, 11
+ Range: natural integers; should be a power of 2 minus one
+ Suggested: 0, 63, 1023, 4095, 16383
3.8 SVN_UNALIGNED_ACCESS_IS_OK
@@ -457,5 +460,10 @@ SVN_I_LIKE_LATENCY_SO_IGNORE_HTTPV2
advertisement of HTTPv2 protocol support (if any), effectively
causing them to only speak our original HTTP protocol.
+7.7 SVN_SVNMUCC_IS_SVNSYITF
+
+ Scope: 'make install-tools'
+ Purpose: Symlinks $prefix/bin/svnsyitf to $prefix/bin/svnmucc
+
* (TODO: others)
Modified: subversion/branches/fix-rdump-editor/notes/merge-tracking/func-spec.html
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/merge-tracking/func-spec.html?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/merge-tracking/func-spec.html (original)
+++ subversion/branches/fix-rdump-editor/notes/merge-tracking/func-spec.html Wed May 16 20:32:43 2012
@@ -149,44 +149,163 @@ mergeinfo for the merge is set on the de
</ul>
+<h3>Rationale</h3>
+
+<p><em>[JAF] The above may be the actual behaviour but sounds too simplistic
+ to be the desired behaviour. Although a simple depth attribute is
+ recorded for each dir in the WC, the ambient depth of a dir in the WC is
+ not simply one of empty/files/immediates/infinity, but rather is a tree in
+ which different branches are populated to different depths. Surely the
+ merge ought to respond to the ambient depth rather than the simple depth
+ attribute.</em></p>
+
+<p><em>[JAF] It's not clear whether an incoming addition should be honoured
+ if the added node would fall outside the ambient depth. The sparse-
+ directories design doesn't seem to address this case for updates, let
+ alone merges. It would be silly if a merge could delete such a node (that
+ was present in the WC despite being outside its parent's 'depth'
+ attribute) and could not then re-add a node of the same name in order to
+ perform both halves of an incoming replacement. <a
+ href="http://subversion.tigris.org/issues/show_bug.cgi?id=4164" >Issue
+ #4164 "inconsistencies in merge handling of adds vs. edits in shallow
+ targets"</a> is related.</em></p>
+
+<p>See <a href="../sparse-directories.txt">sparse-directories design</a>.</p>
+
</div> <!-- sparse-checkouts -->
<div class="h2" id="switched-paths">
<h2>Switched Paths</h2>
-<p>Switched paths are treated as the root of the working copy regarding
-merge info inheritance and elision, specifically:</p>
+<p>Switched paths are treated as the root of a working copy regarding
+mergeinfo inheritance, recording, and elision. Specifically, for a
+merge target with an arbitrary switched subtree:</p>
+
+<pre>
+ WC-Root
+ |
+ Target
+ |
+ SSP
+ | \
+ | \
+ SS SSS
+
+ Target - The WC target of the merge operation (may be same as WC-Root)
+ SSP - Switched Subtree Parent (may be same as Target)
+ SSPS - Switched Subtree Sibling (zero or more)
+ SS - Switched Subtree</pre>
+
+<p>Note: If SS is itself the target of the merge, then the no special
+handling is needed, the merge takes place as if SS is the root of the WC.</p>
+
+<ul>
+ <li><strong>Inheritance:</strong> If SS has no explicit mergeinfo of its
+ own, it inherits mergeinfo not from its WC parent (SSP) but from its
+ repository parent:</li>
+
+<pre>
+ WC-Root
+ |
+ Target
+ |
+ V
+ SSP
+SSRP.. | \
+ \ | \
+ V x V
+ SS SSS
+
+SSRP - Switched subtree's repository parent
+--> Mergeinfo inheritance
+--x No mergeinfo inheritance</pre>
+
+ <li><strong>Recording a Merge:</strong> If we merge revision N from ^/SRC,
+ mergeinfo is recorded like so (note that mergeinfo source '/SRC' is not
+ literal for children of 'Target' but would be adjusted for the path-wise
+ differences between the root of the merge target and the subtree in
+ question):</li>
+
+<pre>
+ WC-Root
+ |
+ Target ('/SRC:N')
+ |
+ SSP('/SRC:N*')
+ | \
+ | \
+ | SSS('/SRC:N')
+ |
+ SS('/SRC:N' and possibly the mergeinfo
+ inherited from SSRP if SS
+ had no pre-existing explicit
+ mergeinfo)</pre>
+
+ <li><strong>Elision:</strong> Mergeinfo on switched paths never elides to
+ its working copy parents:</li>
+
+<pre>
+ WC-Root
+ ^
+ |
+ Target
+ ^
+ |
+ SSP
+ x ^
+ | \
+ | \
+ SS SSS
+
+--> Mergeinfo elision possible
+--x No mergeinfo elision possible</pre>
-<ul>
- <li>Merge rev N to switched PATH which has no explicit merge info: PATH
- does not inherit merge info from its working copy ancestors. PATH gets
- merge info for rev N plus any inherited mergeinfo from the repository.</li>
-
- <li>Merge rev N to PATH with switched CHILD: If CHILD has no explicit
- mergeinfo it does not inherit merge info from its working copy ancestors.
- Instead CHILD gets merge info for rev N plus any inherited mergeinfo from
- the repository. Regardless of wether CHILD has explicit mergeinfo,
- CHILD's immediate PARENT (which may be the same as PATH) gets
- non-inheritable mergeinfo added for rev N. If PARENT didn't have
- pre-existing mergeinfo it will have mergeinfo added. If CHILD has an
- unswitched SIBLING, then SIBLING will get a full set of mergeinfo since
- SIBLING and CHILD's common PARENT gets non-inheritable mergeinfo for this
- merge. Again, like PARENT, if SIBLING does not have pre-existing
- mergeinfo it will have mergeinfo added.
- </li>
-
- <li>Elision: Merge info on switched paths never elides.</li>
-
- <li>Switch PATH which has <em>committed</em> merge info or switch PATH which
- has a CHILD with <em>committed</em> mergeinfo: PATH's / CHILD's mergeinfo
- is <em>replaced</em> by the explicit mergeinfo from the repository.</li>
-
- <li>Switch PATH which has <em>local</em> merge info or switch PATH which has
- a CHILD with <em>local</em> mergeinfo: PATH's / CHILDS's local mergeinfo
- is <em>merged</em> with explicit or inherited mergeinfo from the repository.
- </li>
</ul>
+<h3>Delete</h3>
+
+<p><a href="http://subversion.tigris.org/issues/show_bug.cgi?id=4163"
+ >Issue #4163 "merged deletion of switched subtrees records non-inheritable
+ mergeinfo"</a>: If a merge deletes the path SS, the desired behaviour
+ is currently undefined and the actual behaviour is that a commit will
+ delete <strong>both</strong> SS (from SSRP) and SS@BASE (from SSP).</p>
+
+<h3>Rationale</h3>
+
+<p>Why does merging work this way with switched subtrees?</p>
+
+<p>If a subtree (SS) is switched, that means the user has chosen for
+ the time being to work with a substitute for the original subtree
+ (SS@BASE), knowing that any modifications made in SS can be
+ committed only to the repository location of SS and the original
+ subtree SS@BASE remains hidden and unaffected.</p>
+
+<p>The general semantics of a merge is to apply local modifications
+ to the working copy and record the merge as having been applied
+ to the tree that is represented by the working copy.</p>
+
+<p>Merge tracking should ensure that the subtree of the merge that
+ goes into SS is recorded as being applied to SS, while the
+ subtree SS@BASE should be recorded as not having received that
+ merge.</p>
+
+<p>Since the working copy represents parts of two different branches,
+ two parts of the merge are thus applied to the two different
+ branches, and recorded as such when the user commits the result.</p>
+
+<p>If the user is doing a merge that may affect SS, it is reasonable
+ to assume that SS is an alternative variant of SS@BASE rather than
+ some totally unrelated item. So, in terms of Subversion's loose
+ branching semantics, SS is a 'branch' of SS@BASE. If the user
+ chooses to merge when the assumption is false and SS doesn't have
+ a sensible branching relationship with SS@BASE, the result will be
+ nonsensical or, in concrete terms, there will be merge conflicts.</p>
+
+<p>Note: Many typical branching policies would forbid committing to
+ two branches at once, let alone committing merges to two branches
+ at once. However, the user may have reasons for doing this merge
+ without intending to commit the result as-is.</p>
+
</div> <!-- switched-paths -->
<div class="h2" id="prop-change">
Modified: subversion/branches/fix-rdump-editor/notes/moves
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/moves?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/moves (original)
+++ subversion/branches/fix-rdump-editor/notes/moves Wed May 16 20:32:43 2012
@@ -39,29 +39,22 @@ The following columns in the NODES table
moves from copies:
/* Boolean value, specifying if this node was moved here (rather than just
- copied). The source of the move is implied by a different node with
- a moved_to column pointing at this node. */
+ copied). This is set on all the nodes in the moved tree. The source of
+ the move is implied by a different node with a moved_to column pointing
+ at the root node of the moved tree. */
moved_here INTEGER,
/* If the underlying node was moved away (rather than just deleted), this
- specifies the local_relpath of where the BASE node was moved to.
+ specifies the local_relpath of where the node was moved to.
This is set only on the root of a move, and is NULL for all children.
- Note that moved_to never refers to *this* node. It always refers
- to the "underlying" node in the BASE tree. A non-NULL moved_to column
- is only valid in rows where op_depth == 0. */
+ The op-depth of the moved-to node is not recorded. A moved_to path
+ always points at a node within the highest op-depth layer at the
+ destination. This invariant must be maintained by operations which
+ change existing move information. */
moved_to TEXT,
-Some new queries were added which use these columns:
-
- STMT_SELECT_MOVED_FROM_RELPATH
- STMT_UPDATE_MOVED_TO_RELPATH
- STMT_CLEAR_MOVED_TO_RELPATH
- STMT_CLEAR_MOVED_TO_RELPATH_RECURSIVE
- STMT_SELECT_MOVED_HERE_CHILDREN
-
-More queries might be needed (TBD).
-
+Many queries were added or changed to use these columns.
== libsvn_wc ==
@@ -81,6 +74,8 @@ private libsvn_wc API:
the node at the moved_from abspath
More API changes might be needed (TBD).
+In particular, scan_deletion may need to return a list of moves
+in the multi-layer case (http://wiki.apache.org/subversion/MultiLayerMoves)
We might require a working copy upgrade when going from 1.7 to 1.8,
and only allow new move functionality to be used with 1.8 working copies.
Modified: subversion/branches/fix-rdump-editor/notes/ra-serf-testing.txt
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/ra-serf-testing.txt?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/ra-serf-testing.txt (original)
+++ subversion/branches/fix-rdump-editor/notes/ra-serf-testing.txt Wed May 16 20:32:43 2012
@@ -1,3 +1,5 @@
+[ THE CUSTOM TESTING CODE DESCRIBED BELOW WAS REMOVED in r1302567 ]
+
For the 1.7 release, ra_serf grew a new internal feature to "pause"
the parsing of (large) XML response bodies. This file intends to
document the strategy for testing this new feature.
Modified: subversion/branches/fix-rdump-editor/notes/sparse-directories.txt
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/sparse-directories.txt?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/sparse-directories.txt (original)
+++ subversion/branches/fix-rdump-editor/notes/sparse-directories.txt Wed May 16 20:32:43 2012
@@ -410,7 +410,21 @@ Contents
7. Work Remaining
=================
- The list of outstanding issues is shown by this issue tracker query
- (showing Summary fields that start with "[sparse-directories]"):
+ * The list of outstanding issues is shown by this issue tracker query
+ (showing Summary fields that start with "[sparse-directories]"):
<http://subversion.tigris.org/issues/buglist.cgi?component=subversion&issue_status=NEW&issue_status=STARTED&issue_status=REOPENED&short_desc=%5Bsparse-directories%5D&short_desc_type=casesubstring>
+
+ * Update this doc (sections 1 & 6) to WC-NG.
+
+ * Clarify whether an update should honour an incoming change that
+ adds a new node outside the ambient depth. For example, if a new
+ node 'A/foo' has been added in the repository, and directory 'A' is
+ depth-empty in the WC (and an 'A/foo' is not already present),
+ should the update add 'A/foo', or should it skip it on the basis
+ that it's outside the current ambient depth? If not, an update (or
+ merge) could delete an earlier node at the path 'A/foo' (that was
+ present in the WC despite being outside its parent's 'depth'
+ attribute) but could not then re-add a node of the same name in
+ order to perform both halves of an incoming replacement. Wouldn't
+ that be silly?
Modified: subversion/branches/fix-rdump-editor/notes/wc-ng/conflict-storage
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/notes/wc-ng/conflict-storage?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/notes/wc-ng/conflict-storage (original)
+++ subversion/branches/fix-rdump-editor/notes/wc-ng/conflict-storage Wed May 16 20:32:43 2012
@@ -200,7 +200,7 @@ Tree conflicts
Tree conflicts exist on files or directories.
### JAF: And symlinks, I presume - or, if not, why not?
-### stsp: Symlinks are resolved before retreiving conflict information.,
+### stsp: Symlinks are resolved before retreiving conflict information.
The following information is stored if there is a tree conflict on the node:
@@ -212,8 +212,18 @@ The following information is stored if t
LOCAL_CHANGE is the local change which conflicted with the
incoming change during the operation. Possible values are "edit", "add",
-"delete", "rename", "replace", "obstructed", "missing", and "unversioned"
-(### possibly collapse "unversioned" with "obstructed"?).
+"delete", "rename", "replace", "obstructed", "missing", "unversioned",
+"moved-away", "moved-here", and "copied-here".
+
+### possibly collapse "unversioned" with "obstructed"?
+
+### what is "replace"? we should probably have "replace-add",
+### "replace-moved-away", "replace-moved-here", and "replace-copied-here"
+### hrm. this probably isn't the right representation. "replace-add"
+### says how the new node arrived, but not how the original departed.
+### was it a deleted or moved-away? for example, a local-deleted
+### followed by an add, followed by an incoming-delete should probably
+### be deemed "no conflict".
ORIGINAL_NODE_KIND is the kind of the node in the BASE tree.
MINE_NODE_KIND is the kind of the node from the WORKING tree at the
@@ -221,7 +231,9 @@ time the conflict was flagged.
INCOMING_CHANGE is the incoming change which conflicted with the
local change during the operation. Possible values are "edit", "add",
-"delete", "rename", and "replace".
+"delete", "rename", "replace", "moved-away", "moved-here", and
+"copied-here".
+### see concerns above about LOCAL_CHANGE.
The *_SHA1 sum fields are only present if {ORIGINAL,MINE,INCOMING}_NODE_KIND
is "file".
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.cpp?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.cpp (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.cpp Wed May 16 20:32:43 2012
@@ -936,7 +936,7 @@ void SVNClient::diff(const char *target1
OutputStream &outputStream, svn_depth_t depth,
StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps)
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly)
{
SVN::Pool subPool(pool);
const char *c_relToDir = relativeToDir ?
@@ -973,6 +973,7 @@ void SVNClient::diff(const char *target1
showCopiesAsAdds,
force,
ignoreProps,
+ propsOnly,
FALSE, /* use_git_diff_format */
SVN_APR_LOCALE_CHARSET,
outputStream.getStream(subPool),
@@ -1000,6 +1001,7 @@ void SVNClient::diff(const char *target1
showCopiesAsAdds,
force,
ignoreProps,
+ propsOnly,
FALSE, /* use_git_diff_format */
SVN_APR_LOCALE_CHARSET,
outputStream.getStream(subPool),
@@ -1016,11 +1018,11 @@ void SVNClient::diff(const char *target1
const char *relativeToDir, OutputStream &outputStream,
svn_depth_t depth, StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps)
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly)
{
diff(target1, revision1, target2, revision2, NULL, relativeToDir,
outputStream, depth, changelists, ignoreAncestry, noDiffDelete, force,
- showCopiesAsAdds, ignoreProps);
+ showCopiesAsAdds, ignoreProps, propsOnly);
}
void SVNClient::diff(const char *target, Revision &pegRevision,
@@ -1028,12 +1030,12 @@ void SVNClient::diff(const char *target,
const char *relativeToDir, OutputStream &outputStream,
svn_depth_t depth, StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps)
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly)
{
diff(target, startRevision, NULL, endRevision, &pegRevision,
relativeToDir, outputStream, depth, changelists,
ignoreAncestry, noDiffDelete, force, showCopiesAsAdds,
- ignoreProps);
+ ignoreProps, propsOnly);
}
void
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.h
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.h?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.h (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/SVNClient.h Wed May 16 20:32:43 2012
@@ -177,13 +177,13 @@ class SVNClient :public SVNBase
const char *relativeToDir, OutputStream &outputStream,
svn_depth_t depth, StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps);
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly);
void diff(const char *target, Revision &pegevision,
Revision &startRevision, Revision &endRevision,
const char *relativeToDir, OutputStream &outputStream,
svn_depth_t depth, StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps);
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly);
void diffSummarize(const char *target1, Revision &revision1,
const char *target2, Revision &revision2,
svn_depth_t depth, StringArray &changelists,
@@ -212,7 +212,7 @@ class SVNClient :public SVNBase
OutputStream &outputStream, svn_depth_t depth,
StringArray &changelists,
bool ignoreAncestry, bool noDiffDelete, bool force,
- bool showCopiesAsAdds, bool ignoreProps);
+ bool showCopiesAsAdds, bool ignoreProps, bool propsOnly);
Path m_lastPath;
ClientContext context;
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNClient.cpp Wed May 16 20:32:43 2012
@@ -1171,12 +1171,12 @@ JNIEXPORT void JNICALL Java_org_apache_s
}
JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZ
+Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZ
(JNIEnv *env, jobject jthis, jstring jtarget1, jobject jrevision1,
jstring jtarget2, jobject jrevision2, jstring jrelativeToDir,
jobject jstream, jobject jdepth, jobject jchangelists,
jboolean jignoreAncestry, jboolean jnoDiffDeleted, jboolean jforce,
- jboolean jcopiesAsAdds, jboolean jignoreProps)
+ jboolean jcopiesAsAdds, jboolean jignoreProps, jboolean jpropsOnly)
{
JNIEntry(SVNClient, diff);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -1217,16 +1217,17 @@ Java_org_apache_subversion_javahl_SVNCli
EnumMapper::toDepth(jdepth), changelists,
jignoreAncestry ? true:false,
jnoDiffDeleted ? true:false, jforce ? true:false,
- jcopiesAsAdds ? true:false, jignoreProps ? true:false);
+ jcopiesAsAdds ? true:false, jignoreProps ? true:false,
+ jpropsOnly ? true:false);
}
JNIEXPORT void JNICALL
-Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZ
+Java_org_apache_subversion_javahl_SVNClient_diff__Ljava_lang_String_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Lorg_apache_subversion_javahl_types_Revision_2Ljava_lang_String_2Ljava_io_OutputStream_2Lorg_apache_subversion_javahl_types_Depth_2Ljava_util_Collection_2ZZZZZZ
(JNIEnv *env, jobject jthis, jstring jtarget, jobject jpegRevision,
jobject jstartRevision, jobject jendRevision, jstring jrelativeToDir,
jobject jstream, jobject jdepth, jobject jchangelists,
jboolean jignoreAncestry, jboolean jnoDiffDeleted, jboolean jforce,
- jboolean jcopiesAsAdds, jboolean jignoreProps)
+ jboolean jcopiesAsAdds, jboolean jignoreProps, jboolean jpropsOnly)
{
JNIEntry(SVNClient, diff);
SVNClient *cl = SVNClient::getCppObject(jthis);
@@ -1267,7 +1268,8 @@ Java_org_apache_subversion_javahl_SVNCli
dataOut, EnumMapper::toDepth(jdepth), changelists,
jignoreAncestry ? true:false,
jnoDiffDeleted ? true:false, jforce ? true:false,
- jcopiesAsAdds ? true:false, jignoreProps ? true:false);
+ jcopiesAsAdds ? true:false, jignoreProps ? true:false,
+ jpropsOnly ? true:false);
}
JNIEXPORT void JNICALL
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java Wed May 16 20:32:43 2012
@@ -544,7 +544,14 @@ public class ClientNotifyInformation ext
failed_forbidden_by_server ("failed forbidden by server"),
/** Operation skipped the path because it was conflicted */
- skip_conflicted ("skipped conflicted path");
+ skip_conflicted ("skipped conflicted path"),
+
+ /** The lock on a file was removed during update */
+ update_broken_lock ("broken lock removed"),
+
+ /** Operation failed because a node is obstructed */
+ failed_obstructed ("failed by obstruction");
+
/**
* The description of the action.
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java Wed May 16 20:32:43 2012
@@ -522,13 +522,14 @@ public interface ISVNClient
* @param copiesAsAdds if set, copied files will be shown in their
* entirety, not as diffs from their sources
* @param ignoreProps don't show property diffs
+ * @param propsOnly show property changes only
* @throws ClientException
*/
void diff(String target1, Revision revision1, String target2,
Revision revision2, String relativeToDir, OutputStream outStream,
Depth depth, Collection<String> changelists,
boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
- boolean copiesAsAdds, boolean ignoreProps)
+ boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly)
throws ClientException;
void diff(String target1, Revision revision1, String target2,
@@ -554,6 +555,7 @@ public interface ISVNClient
* @param copiesAsAdds if set, copied files will be shown in their
* entirety, not as diffs from their sources
* @param ignoreProps don't show property diffs
+ * @param propsOnly show property changes only
* @throws ClientException
*/
void diff(String target, Revision pegRevision, Revision startRevision,
@@ -561,7 +563,7 @@ public interface ISVNClient
OutputStream outStream,
Depth depth, Collection<String> changelists,
boolean ignoreAncestry, boolean noDiffDeleted, boolean force,
- boolean copiesAsAdds, boolean ignoreProps)
+ boolean copiesAsAdds, boolean ignoreProps, boolean propsOnly)
throws ClientException;
void diff(String target, Revision pegRevision, Revision startRevision,
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java Wed May 16 20:32:43 2012
@@ -278,7 +278,7 @@ public class SVNClient implements ISVNCl
OutputStream stream = new FileOutputStream(outFileName);
diff(target1, revision1, target2, revision2, relativeToDir,
stream, depth, changelists, ignoreAncestry, noDiffDeleted,
- force, copiesAsAdds, false);
+ force, copiesAsAdds, false, false);
} catch (FileNotFoundException ex) {
throw ClientException.fromException(ex);
}
@@ -290,7 +290,7 @@ public class SVNClient implements ISVNCl
Collection<String> changelists,
boolean ignoreAncestry, boolean noDiffDeleted,
boolean force, boolean copiesAsAdds,
- boolean ignoreProps)
+ boolean ignoreProps, boolean propsOnly)
throws ClientException;
public void diff(String target, Revision pegRevision,
@@ -305,7 +305,7 @@ public class SVNClient implements ISVNCl
OutputStream stream = new FileOutputStream(outFileName);
diff(target, pegRevision, startRevision, endRevision,
relativeToDir, stream, depth, changelists, ignoreAncestry,
- noDiffDeleted, force, copiesAsAdds, false);
+ noDiffDeleted, force, copiesAsAdds, false, false);
} catch (FileNotFoundException ex) {
throw ClientException.fromException(ex);
}
@@ -317,7 +317,7 @@ public class SVNClient implements ISVNCl
Depth depth, Collection<String> changelists,
boolean ignoreAncestry, boolean noDiffDeleted,
boolean force, boolean copiesAsAdds,
- boolean ignoreProps)
+ boolean ignoreProps, boolean propsOnly)
throws ClientException;
public native void diffSummarize(String target1, Revision revision1,
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/perl/native/t/3client.t
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/perl/native/t/3client.t?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/perl/native/t/3client.t (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/perl/native/t/3client.t Wed May 16 20:32:43 2012
@@ -58,7 +58,12 @@ my $current_rev = 0;
$SVN::Error::handler = undef;
# Get username we are running as
-my $username = getlogin() || getpwuid($>);
+my $username;
+if ($^O eq 'MSWin32') {
+ $username = getlogin();
+} else {
+ $username = getpwuid($>) || getlogin();
+}
# This is ugly to create the test repo with SVN::Repos, but
# it seems to be the most reliable way.
@@ -337,8 +342,14 @@ is($ctx->blame("$reposurl/foo",'HEAD','H
'author param is expected' .
'value');
ok($date,'date is defined');
- is($line,'foobar',
- 'line is expected value');
+ if ($^O eq 'MSWin32') {
+ #### Why two \r-s?
+ is($line,"foobar\r\r",
+ 'line is expected value');
+ } else {
+ is($line,'foobar',
+ 'line is expected value');
+ }
isa_ok($pool,'_p_apr_pool_t',
'pool param is ' .
'_p_apr_pool_t');
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/client.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/client.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/client.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/client.py Wed May 16 20:32:43 2012
@@ -27,4 +27,5 @@ from libsvn.client import *
from svn.core import _unprefix_names
_unprefix_names(locals(), 'svn_client_')
_unprefix_names(locals(), 'SVN_CLIENT_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/core.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/core.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/core.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/core.py Wed May 16 20:32:43 2012
@@ -27,6 +27,44 @@ from libsvn.core import *
import libsvn.core as _libsvncore
import atexit as _atexit
import sys
+__all__ = [
+ # Symbols that 'import *' used to pull (in 1.7)
+ 'Pool',
+ 'SVNSYNC_PROP_CURRENTLY_COPYING',
+ 'SVNSYNC_PROP_FROM_URL',
+ 'SVNSYNC_PROP_FROM_UUID',
+ 'SVNSYNC_PROP_LAST_MERGED_REV',
+ 'SVNSYNC_PROP_LOCK',
+ 'SVNSYNC_PROP_PREFIX',
+ 'SubversionException',
+ # 'apr_array_header_t',
+ # 'apr_file_open_stderr',
+ # 'apr_file_open_stdout',
+ # 'apr_file_t',
+ # 'apr_hash_t',
+ # 'apr_initialize',
+ # 'apr_pool_clear',
+ # 'apr_pool_destroy',
+ # 'apr_pool_t',
+ # 'apr_terminate',
+ # 'apr_time_ansi_put',
+ # 'run_app',
+
+ # Symbols defined explicitly below.
+ 'SVN_IGNORED_REVNUM',
+ 'SVN_INVALID_REVNUM',
+ 'svn_path_compare_paths',
+ 'svn_mergeinfo_merge',
+ 'svn_mergeinfo_sort',
+ 'svn_rangelist_merge',
+ 'svn_rangelist_reverse',
+ # 'Stream',
+ # 'apr_initialize',
+ # 'apr_terminate',
+ 'svn_pool_create',
+ 'svn_pool_destroy',
+ 'svn_pool_clear',
+]
class SubversionException(Exception):
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/delta.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/delta.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/delta.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/delta.py Wed May 16 20:32:43 2012
@@ -27,6 +27,7 @@ from libsvn.delta import *
from svn.core import _unprefix_names
_unprefix_names(locals(), 'svn_delta_')
_unprefix_names(locals(), 'svn_txdelta_', 'tx_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
# Force our accessor since it appears that there isn't a more civilized way
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/diff.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/diff.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/diff.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/diff.py Wed May 16 20:32:43 2012
@@ -26,4 +26,5 @@
from libsvn.diff import *
from svn.core import _unprefix_names
_unprefix_names(locals(), 'svn_diff_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/fs.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/fs.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/fs.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/fs.py Wed May 16 20:32:43 2012
@@ -27,6 +27,7 @@ from libsvn.fs import *
from svn.core import _unprefix_names, Pool
_unprefix_names(locals(), 'svn_fs_')
_unprefix_names(locals(), 'SVN_FS_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/ra.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/ra.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/ra.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/ra.py Wed May 16 20:32:43 2012
@@ -27,6 +27,7 @@ from libsvn.ra import *
from svn.core import _unprefix_names
_unprefix_names(locals(), 'svn_ra_')
_unprefix_names(locals(), 'SVN_RA_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
class Callbacks:
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/repos.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/repos.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/repos.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/repos.py Wed May 16 20:32:43 2012
@@ -27,6 +27,7 @@ from libsvn.repos import *
from svn.core import _unprefix_names, Pool
_unprefix_names(locals(), 'svn_repos_')
_unprefix_names(locals(), 'SVN_REPOS_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/wc.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/wc.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/svn/wc.py Wed May 16 20:32:43 2012
@@ -27,6 +27,7 @@ from libsvn.wc import *
from svn.core import _unprefix_names
_unprefix_names(locals(), 'svn_wc_')
_unprefix_names(locals(), 'SVN_WC_')
+__all__ = filter(lambda x: x.lower().startswith('svn_'), locals().keys())
del _unprefix_names
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/tests/pool.py
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/tests/pool.py?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/tests/pool.py (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/python/tests/pool.py Wed May 16 20:32:43 2012
@@ -195,10 +195,10 @@ class PoolTestCase(unittest.TestCase):
self.assertNone(anonymous_pool_ref())
# Try to cause a segfault using apr_terminate
- apr_terminate()
- apr_initialize()
- apr_terminate()
- apr_terminate()
+ svn.core.apr_terminate()
+ svn.core.apr_initialize()
+ svn.core.apr_terminate()
+ svn.core.apr_terminate()
# Destroy the application pool
svn_pool_destroy(libsvn.core.application_pool)
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/svn/fs.rb
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/svn/fs.rb?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/svn/fs.rb (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/svn/fs.rb Wed May 16 20:32:43 2012
@@ -415,7 +415,7 @@ module Svn
ignore_ancestry)
end
- def replay(editor, base_dir=nil, low_water_mark=nil, send_deltas=false,
+ def replay(editor, base_dir=nil, low_water_mark=nil, send_deltas=true,
&callback)
base_dir ||= ""
low_water_mark ||= Core::INVALID_REVNUM
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_client.rb
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_client.rb?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_client.rb (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_client.rb Wed May 16 20:32:43 2012
@@ -2341,7 +2341,9 @@ class SvnClientTest < Test::Unit::TestCa
def test_changelists_get_without_block
assert_changelists do |ctx, changelist_name|
- ctx.changelists(changelist_name, @wc_path)
+ changelists = ctx.changelists(changelist_name, @wc_path)
+ changelists.each_value { |v| v.sort! }
+ changelists
end
end
@@ -2351,6 +2353,7 @@ class SvnClientTest < Test::Unit::TestCa
ctx.changelists(changelist_name, @wc_path) do |path,cl_name|
changelists[cl_name] << path
end
+ changelists.each_value { |v| v.sort! }
changelists
end
end
Modified: subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_wc.rb
URL: http://svn.apache.org/viewvc/subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_wc.rb?rev=1339349&r1=1339348&r2=1339349&view=diff
==============================================================================
--- subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_wc.rb (original)
+++ subversion/branches/fix-rdump-editor/subversion/bindings/swig/ruby/test/test_wc.rb Wed May 16 20:32:43 2012
@@ -326,12 +326,16 @@ class SvnWcTest < Test::Unit::TestCase
ignored_errors = []
callbacks.ignored_errors = ignored_errors
access.walk_entries(@wc_path, callbacks)
+ sorted_ignored_errors = ignored_errors.sort_by {|path, err| path}
+ sorted_ignored_errors = sorted_ignored_errors.collect! do |path, err|
+ [path, err.class]
+ end
assert_equal([
[@wc_path, Svn::Error::Cancelled],
[path1, Svn::Error::Cancelled],
[path2, Svn::Error::Cancelled],
],
- ignored_errors.collect {|path, err| [path, err.class]})
+ sorted_ignored_errors)
end
end
end
@@ -747,14 +751,15 @@ EOE
:file_changed_prop_name => prop_name,
:file_changed_prop_value => prop_value,
}
- expected_props, actual_result = yield(property_info, callbacks.result)
+ sorted_result = callbacks.result.sort_by {|r| r.first.to_s}
+ expected_props, actual_result = yield(property_info, sorted_result)
dir_changed_props, file_changed_props, empty_changed_props = expected_props
assert_equal([
[:dir_props_changed, @wc_path, dir_changed_props],
- [:file_changed, path1, file_changed_props],
[:file_added, path2, empty_changed_props],
+ [:file_changed, path1, file_changed_props],
],
- callbacks.result)
+ sorted_result)
end
end
end