Rev 1930: Merge new subvertpy. in file:///data/jelmer/bzr-svn/trunk/
Jelmer Vernooij
jelmer at samba.org
Mon Oct 6 16:00:32 BST 2008
At file:///data/jelmer/bzr-svn/trunk/
------------------------------------------------------------
revno: 1930
revision-id: jelmer at samba.org-20081006150030-l1ux7ua7diu4ia4d
parent: jelmer at samba.org-20081002211828-68ls9ejnr9h2xmyy
parent: jelmer at samba.org-20081006145521-053crzkfoxq8vbkj
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Mon 2008-10-06 17:00:30 +0200
message:
Merge new subvertpy.
added:
subvertpy/TODO todo-20081005190627-4brj2368nxwmb0bp-1
subvertpy/subvertpy/marshall.py marshall.py-20081006140850-jzf2dbt55rwefdqm-1
subvertpy/subvertpy/server.py server.py-20081006143330-f9p0l7eih6izgoct-1
subvertpy/subvertpy/tests/test_marshall.py test_marshall.py-20081006140936-tuh5e2o2httgadkd-1
modified:
subvertpy/AUTHORS authors-20081002184818-kozkud4dvhmbez8a-1
subvertpy/Makefile makefile-20081002202532-xkdtg6p584inuoya-1
subvertpy/subvertpy/__init__.py core.pyx-20080313210413-17k59slolpfe5kdq-1
subvertpy/subvertpy/properties.py util.py-20080502170127-o220e9py99vt69s6-1
subvertpy/subvertpy/tests/__init__.py __init__.py-20081002194117-jwf9payoee8eqz7g-1
subvertpy/subvertpy/tests/test_client.py test_client.py-20080603021344-lmgexez0yoyp9b1s-1
subvertpy/subvertpy/tests/test_ra.py test_ra.py-20080313141743-uzsm7ejitrlqone5-1
------------------------------------------------------------
revno: 1925.1.13
revision-id: jelmer at samba.org-20081006145521-053crzkfoxq8vbkj
parent: jelmer at samba.org-20081006145319-vhmi2ifk7wc8vyyo
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Mon 2008-10-06 16:55:21 +0200
message:
Fix import.
modified:
subvertpy/properties.py util.py-20080502170127-o220e9py99vt69s6-1
------------------------------------------------------------
revno: 1925.1.12
revision-id: jelmer at samba.org-20081006145319-vhmi2ifk7wc8vyyo
parent: jelmer at samba.org-20081006145212-3x3na427vstryaat
parent: jelmer at samba.org-20081005190804-m8cww5j1jh71ub1x
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Mon 2008-10-06 16:53:19 +0200
message:
merge trunk.
added:
TODO todo-20081005190627-4brj2368nxwmb0bp-1
modified:
AUTHORS authors-20081002184818-kozkud4dvhmbez8a-1
subvertpy/tests/__init__.py __init__.py-20081002194117-jwf9payoee8eqz7g-1
subvertpy/tests/test_ra.py test_ra.py-20080313141743-uzsm7ejitrlqone5-1
------------------------------------------------------------
revno: 1925.3.4
revision-id: jelmer at samba.org-20081005190804-m8cww5j1jh71ub1x
parent: jelmer at samba.org-20081005190632-5ddvwfrd2juxvkh5
parent: jelmer at samba.org-20081003153217-6jhl30rncdbki1h2
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Sun 2008-10-05 21:08:04 +0200
message:
Merge warning changes.
modified:
subvertpy/__init__.py core.pyx-20080313210413-17k59slolpfe5kdq-1
------------------------------------------------------------
revno: 1925.3.3
revision-id: jelmer at samba.org-20081005190632-5ddvwfrd2juxvkh5
parent: jelmer at samba.org-20081005190257-isn3kpdmjj22ifee
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Sun 2008-10-05 21:06:32 +0200
message:
Add TODO file.
added:
TODO todo-20081005190627-4brj2368nxwmb0bp-1
------------------------------------------------------------
revno: 1925.3.2
revision-id: jelmer at samba.org-20081005190257-isn3kpdmjj22ifee
parent: jelmer at samba.org-20081005190032-h7bohnbgfymrnsc1
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Sun 2008-10-05 21:02:57 +0200
message:
Add Alexey.
modified:
AUTHORS authors-20081002184818-kozkud4dvhmbez8a-1
------------------------------------------------------------
revno: 1925.3.1
revision-id: jelmer at samba.org-20081005190032-h7bohnbgfymrnsc1
parent: jelmer at samba.org-20081002211756-l2qo3remar7o21sz
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Sun 2008-10-05 21:00:32 +0200
message:
Add test for ra.get_file()
modified:
subvertpy/tests/__init__.py __init__.py-20081002194117-jwf9payoee8eqz7g-1
subvertpy/tests/test_client.py test_client.py-20080603021344-lmgexez0yoyp9b1s-1
subvertpy/tests/test_ra.py test_ra.py-20080313141743-uzsm7ejitrlqone5-1
------------------------------------------------------------
revno: 1925.1.11
revision-id: jelmer at samba.org-20081006145212-3x3na427vstryaat
parent: jelmer at samba.org-20081003153217-6jhl30rncdbki1h2
parent: jelmer at samba.org-20081006145153-bw7mize9cjrp4vny
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Mon 2008-10-06 16:52:12 +0200
message:
Merge initial work on server support.
added:
subvertpy/marshall.py marshall.py-20081006140850-jzf2dbt55rwefdqm-1
subvertpy/server.py server.py-20081006143330-f9p0l7eih6izgoct-1
subvertpy/tests/test_marshall.py test_marshall.py-20081006140936-tuh5e2o2httgadkd-1
modified:
Makefile makefile-20081002202532-xkdtg6p584inuoya-1
subvertpy/properties.py util.py-20080502170127-o220e9py99vt69s6-1
subvertpy/tests/test_client.py test_client.py-20080603021344-lmgexez0yoyp9b1s-1
subvertpy/tests/test_ra.py test_ra.py-20080313141743-uzsm7ejitrlqone5-1
------------------------------------------------------------
revno: 1925.2.5
revision-id: jelmer at samba.org-20081006145153-bw7mize9cjrp4vny
parent: jelmer at samba.org-20081006143538-1ebbepd0el66bn6u
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: native
timestamp: Mon 2008-10-06 16:51:53 +0200
message:
Make server abstract.
modified:
subvertpy/properties.py util.py-20080502170127-o220e9py99vt69s6-1
subvertpy/server.py server.py-20081006143330-f9p0l7eih6izgoct-1
subvertpy/tests/test_client.py test_client.py-20080603021344-lmgexez0yoyp9b1s-1
subvertpy/tests/test_ra.py test_ra.py-20080313141743-uzsm7ejitrlqone5-1
------------------------------------------------------------
revno: 1925.2.4
revision-id: jelmer at samba.org-20081006143538-1ebbepd0el66bn6u
parent: jelmer at samba.org-20081006142732-15824ke4snnijbxw
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: native
timestamp: Mon 2008-10-06 16:35:38 +0200
message:
Import initial work on server support.
added:
subvertpy/server.py server.py-20081006143330-f9p0l7eih6izgoct-1
------------------------------------------------------------
revno: 1925.2.3
revision-id: jelmer at samba.org-20081006142732-15824ke4snnijbxw
parent: jelmer at samba.org-20081006142530-kkrskonz776yxmn7
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: native
timestamp: Mon 2008-10-06 16:27:32 +0200
message:
Add build-inplace.
modified:
Makefile makefile-20081002202532-xkdtg6p584inuoya-1
------------------------------------------------------------
revno: 1925.2.2
revision-id: jelmer at samba.org-20081006142530-kkrskonz776yxmn7
parent: jelmer at samba.org-20081006141031-1mlz9enp8w6nd6xa
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: native
timestamp: Mon 2008-10-06 16:25:30 +0200
message:
Fix marshall tests.
modified:
subvertpy/tests/test_marshall.py test_marshall.py-20081006140936-tuh5e2o2httgadkd-1
------------------------------------------------------------
revno: 1925.2.1
revision-id: jelmer at samba.org-20081006141031-1mlz9enp8w6nd6xa
parent: jelmer at samba.org-20081003153217-6jhl30rncdbki1h2
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: native
timestamp: Mon 2008-10-06 16:10:31 +0200
message:
Import marshall code.
added:
subvertpy/marshall.py marshall.py-20081006140850-jzf2dbt55rwefdqm-1
subvertpy/tests/test_marshall.py test_marshall.py-20081006140936-tuh5e2o2httgadkd-1
------------------------------------------------------------
revno: 1925.1.10
revision-id: jelmer at samba.org-20081003153217-6jhl30rncdbki1h2
parent: jelmer at samba.org-20081002211756-l2qo3remar7o21sz
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: trunk
timestamp: Fri 2008-10-03 17:32:17 +0200
message:
Warn about subvertpy rather than bzr-svn.
modified:
subvertpy/__init__.py core.pyx-20080313210413-17k59slolpfe5kdq-1
=== modified file 'subvertpy/AUTHORS'
--- a/subvertpy/AUTHORS 2008-10-02 19:20:17 +0000
+++ b/subvertpy/AUTHORS 2008-10-05 19:02:57 +0000
@@ -2,6 +2,7 @@
Jelmer Vernooij <jelmer at samba.org>
Windows support:
+Alexey Borzenkov
Mark Hammond
Adrian Wilkins
=== modified file 'subvertpy/Makefile'
--- a/subvertpy/Makefile 2008-10-02 20:25:33 +0000
+++ b/subvertpy/Makefile 2008-10-06 14:27:32 +0000
@@ -2,11 +2,14 @@
SETUP = $(PYTHON) setup.py
TRIAL = trial
-all: build
+all: build build-inplace
build::
$(SETUP) build
+build-inplace::
+ $(SETUP) build_ext --inplace
+
install::
$(SETUP) install
=== added file 'subvertpy/TODO'
--- a/subvertpy/TODO 1970-01-01 00:00:00 +0000
+++ b/subvertpy/TODO 2008-10-05 19:06:32 +0000
@@ -0,0 +1,2 @@
+- Remove last dependencies on bzrlib in the testsuite
+- Add more docstrings
=== modified file 'subvertpy/subvertpy/__init__.py'
--- a/subvertpy/subvertpy/__init__.py 2008-10-02 20:45:22 +0000
+++ b/subvertpy/subvertpy/__init__.py 2008-10-03 15:32:17 +0000
@@ -76,8 +76,8 @@
import client, ra, repos, wc
for x in client, ra, repos, wc:
if not _check_mtime(x):
- warn("bzr-svn extensions are outdated and need to be rebuilt")
+ warn("subvertpy extensions are outdated and need to be rebuilt")
break
except ImportError:
- raise ImportError("Unable to load bzr-svn extensions - did you build it?")
+ raise ImportError("Unable to load subvertpy extensions - did you build it?")
=== added file 'subvertpy/subvertpy/marshall.py'
--- a/subvertpy/subvertpy/marshall.py 1970-01-01 00:00:00 +0000
+++ b/subvertpy/subvertpy/marshall.py 2008-10-06 14:10:31 +0000
@@ -0,0 +1,107 @@
+# Copyright (C) 2006-2007 Jelmer Vernooij <jelmer at samba.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+class literal:
+ def __init__(self, txt):
+ self.txt = txt
+
+ def __str__(self):
+ return self.txt
+
+ def __repr__(self):
+ return self.txt
+
+# 1. Syntactic structure
+# ----------------------
+#
+# The Subversion protocol is specified in terms of the following
+# syntactic elements, specified using ABNF [RFC 2234]:
+#
+# item = word / number / string / list
+# word = ALPHA *(ALPHA / DIGIT / "-") space
+# number = 1*DIGIT space
+# string = 1*DIGIT ":" *OCTET space
+# ; digits give the byte count of the *OCTET portion
+# list = "(" space *item ")" space
+# space = 1*(SP / LF)
+#
+
+class MarshallError(Exception):
+ """A Marshall error."""
+
+
+def marshall(x):
+ if isinstance(x, int):
+ return "%d " % x
+ elif isinstance(x, list) or isinstance(x, tuple):
+ return "( " + "".join(map(marshall, x)) + ") "
+ elif isinstance(x, literal):
+ return "%s " % x
+ elif isinstance(x, basestring):
+ return "%d:%s " % (len(x), x)
+ raise MarshallError("Unable to marshall type %s" % x)
+
+
+def unmarshall(x):
+ whitespace = ['\n', ' ']
+ if len(x) == 0:
+ raise MarshallError("Not enough data")
+ if x[0] == "(" and x[1] == " ": # list follows
+ x = x[2:]
+ ret = []
+ try:
+ while x[0] != ")":
+ (x, n) = unmarshall(x)
+ ret.append(n)
+ except IndexError:
+ raise MarshallError("List not terminated")
+
+ if not x[1] in whitespace:
+ raise MarshallError("Expected space, got %c" % x[1])
+
+ return (x[2:], ret)
+ elif x[0].isdigit():
+ num = ""
+ # Check if this is a string or a number
+ while x[0].isdigit():
+ num += x[0]
+ x = x[1:]
+ num = int(num)
+
+ if x[0] in whitespace:
+ return (x[1:], num)
+ elif x[0] == ":":
+ if len(x) < num:
+ raise MarshallError("Expected string of length %r" % num)
+ return (x[num+2:], x[1:num+1])
+ else:
+ raise MarshallError("Expected whitespace or ':', got '%c" % x[0])
+ elif x[0].isalpha():
+ ret = ""
+ # Parse literal
+ try:
+ while x[0].isalpha() or x[0].isdigit() or x[0] == '-':
+ ret += x[0]
+ x = x[1:]
+ except IndexError:
+ raise MarshallError("Expected literal")
+
+ if not x[0] in whitespace:
+ raise MarshallError("Expected whitespace, got %c" % x[0])
+
+ return (x[1:], ret)
+ else:
+ raise MarshallError("Unexpected character '%c'" % x[0])
=== modified file 'subvertpy/subvertpy/properties.py'
--- a/subvertpy/subvertpy/properties.py 2008-10-02 20:22:45 +0000
+++ b/subvertpy/subvertpy/properties.py 2008-10-06 14:55:21 +0000
@@ -13,8 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import bisect
-from bzrlib import urlutils
+import bisect, urllib
class InvalidExternalsDescription(Exception):
@@ -100,7 +99,7 @@
raise NotImplementedError("Relative to the scheme externals not yet supported")
if relurl.startswith("^/"):
raise NotImplementedError("Relative to the repository root externals not yet supported")
- ret[path] = (revno, "%s/%s" % (base_url, relurl))
+ ret[path] = (revno, urllib.basejoin(base_url, relurl))
return ret
=== added file 'subvertpy/subvertpy/server.py'
--- a/subvertpy/subvertpy/server.py 1970-01-01 00:00:00 +0000
+++ b/subvertpy/subvertpy/server.py 2008-10-06 14:51:53 +0000
@@ -0,0 +1,221 @@
+# Copyright (C) 2006 Jelmer Vernooij <jelmer at samba.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import copy
+import os
+import time
+
+from subvertpy import SVN_NODE_NONE, SVN_NODE_FILE, SVN_NODE_DIR
+from subvertpy.marshall import marshall, unmarshall, literal, MarshallError
+
+
+class ServerBackend:
+
+ def open_repository(self, location):
+ raise NotImplementedError(self.open_repository)
+
+
+class ServerRepositoryBackend:
+
+ def get_uuid(self):
+ raise NotImplementedError(self.get_uuid)
+
+ def get_latest_revnum(self):
+ raise NotImplementedError(self.get_latest_revnum)
+
+
+
+SVN_MAJOR_VERSION = 1
+SVN_MINOR_VERSION = 2
+
+class SVNServer:
+ def __init__(self, backend, recv_fn, send_fn, logf=None):
+ self.backend = backend
+ self.recv_fn = recv_fn
+ self.send_fn = send_fn
+ self.inbuffer = ""
+ self._stop = False
+ self._logf = logf
+
+ def send_greeting(self):
+ self.send_success(
+ SVN_MAJOR_VERSION, SVN_MINOR_VERSION, [literal("ANONYMOUS")], [])
+
+ def send_mechs(self):
+ self.send_success([literal("ANONYMOUS")], "")
+
+ def send_failure(self, *contents):
+ self.send_msg([literal("failure"), list(contents)])
+
+ def send_success(self, *contents):
+ self.send_msg([literal("success"), list(contents)])
+
+ def send_unknown(self, cmd):
+ self.send_failure([210001, "Unknown command '%s'" % cmd, __file__, \
+ 52])
+
+ def get_latest_rev(self):
+ self.send_success([], "")
+ self.send_success(self.repo_backend.get_latest_revnum())
+
+ def check_path(self, path, revnum):
+ return SVN_NODE_DIR
+
+ def log(self, target_path, start_rev, end_rev, changed_paths,
+ strict_node, limit=None):
+ def send_revision(revno, rev):
+ self.send_msg([[], revno, [rev.committer],
+ [time.strftime("%Y-%m-%dT%H:%M:%S.00000Z", time.gmtime(rev.timestamp))],
+ [rev.message]])
+ self.send_success([], "")
+ revno = start_rev[0]
+ i = 0
+ self.branch.repository.lock_read()
+ try:
+ # FIXME: check whether start_rev and end_rev actually exist
+ while revno != end_rev[0]:
+ #TODO: Honor target_path, strict_node, changed_paths
+ if end_rev[0] > revno:
+ revno+=1
+ else:
+ revno-=1
+ if limit != 0 and i == limit:
+ break
+ if revno != 0:
+ send_revision(revno, self.branch.repository.get_revision(self.branch.get_rev_id(revno)))
+ finally:
+ self.branch.repository.unlock()
+
+ self.send_msg(literal("done"))
+ self.send_success()
+
+ def reparent(self, parent):
+ self.send_success([], "")
+ self.send_success()
+
+ def stat(self, path, revnum):
+ self.send_success([], "")
+ self.send_success()
+
+ def update(self, rev, target, recurse):
+ self.send_success([], "")
+ while True:
+ msg = self.recv_msg()
+ assert msg[0] in ["set-path", "finish-report"]
+ if msg[0] == "finish-report":
+ break
+
+ self.send_success([], "")
+ self.send_msg(["target-rev", rev])
+ tree = self.branch.repository.revision_tree(
+ self.branch.get_rev_id(rev[0]))
+ path2id = {}
+ id2path = {}
+ self.send_msg(["open-root", [rev, tree.inventory.root.file_id]])
+ def send_children(self, id):
+ for child in tree.inventory[id].children:
+ if tree.inventory[child].kind in ('symlink', 'file'):
+ self.send_msg(["add-file", [tree.inventory.id2path(child),
+ id, child]])
+ # FIXME
+ self.send_msg(["close-file", [child]])
+ else:
+ self.send_msg(["add-dir", [tree.inventory.id2path(child),
+ id, child]])
+ send_children(child)
+ self.send_msg(["close-dir", [child]])
+ #send_children(tree.inventory.root.file_id)
+ self.send_msg(["close-dir", [tree.inventory.root.file_id]])
+ self.send_msg(["close-edit", []])
+ #msg = self.recv_msg()
+ #self.send_msg(msg)
+
+
+ commands = {
+ "get-latest-rev": get_latest_rev,
+ "log": log,
+ "update": update,
+ "check-path": check_path,
+ "reparent": reparent,
+ "stat": stat,
+ # FIXME: get-dated-rev
+ # FIXME: rev-proplist
+ # FIXME: rev-prop
+ # FIXME: get-file
+ # FIXME: get-dir
+ # FIXME: check-path
+ # FIXME: switch
+ # FIXME: status
+ # FIXME: diff
+ # FIXME: get-locations
+ # FIXME: get-file-revs
+ # FIXME: replay
+ }
+
+ def send_auth_request(self):
+ pass
+
+ def serve(self):
+ self.send_greeting()
+ (version, capabilities, url) = self.recv_msg()
+ self.capabilities = capabilities
+ self.version = version
+ self.url = url
+ self.mutter("client supports:")
+ self.mutter(" version %r" % version)
+ self.mutter(" capabilities %r " % capabilities)
+ self.send_mechs()
+
+ (mech, args) = self.recv_msg()
+ # TODO: Proper authentication
+ self.send_success()
+
+ import urllib
+ (rooturl, location) = urllib.splithost(url)
+
+ self.repo_backend, self.relpath = self.backend.open_repository(location)
+ self.send_success(self.repo_backend.get_uuid(), url)
+
+ # Expect:
+ while not self._stop:
+ ( cmd, args ) = self.recv_msg()
+ if not self.commands.has_key(cmd):
+ self.send_unknown(cmd)
+ return
+ else:
+ self.commands[cmd](self, *args)
+
+ def close(self):
+ self._stop = True
+
+ def recv_msg(self):
+ # FIXME: Blocking read?
+ while True:
+ try:
+ self.inbuffer += self.recv_fn()
+ (self.inbuffer, ret) = unmarshall(self.inbuffer)
+ self.mutter('in: %r' % ret)
+ return ret
+ except MarshallError, e:
+ self.mutter('ERROR: %r' % e)
+
+ def send_msg(self, data):
+ self.mutter('out: %r' % data)
+ self.send_fn(marshall(data))
+
+ def mutter(self, text):
+ if self._logf is not None:
+ self._logf.write(text)
=== modified file 'subvertpy/subvertpy/tests/__init__.py'
--- a/subvertpy/subvertpy/tests/__init__.py 2008-10-02 19:44:15 +0000
+++ b/subvertpy/subvertpy/tests/__init__.py 2008-10-05 19:00:32 +0000
@@ -16,3 +16,266 @@
"""Tests for subvertpy."""
+from cStringIO import StringIO
+
+# FIXME: Remove dependency on bzrlib
+from bzrlib import osutils, urlutils
+from bzrlib.tests import TestCaseInTempDir
+
+import os, sys
+
+from subvertpy import delta, ra, repos, delta, client, properties
+from subvertpy.ra import Auth, RemoteAccess
+
+
+class TestFileEditor(object):
+ def __init__(self, file):
+ self.file = file
+ self.is_closed = False
+
+ def change_prop(self, name, value):
+ self.file.change_prop(name, value)
+
+ def modify(self, contents=None):
+ if contents is None:
+ contents = osutils.rand_chars(100)
+ txdelta = self.file.apply_textdelta()
+ delta.send_stream(StringIO(contents), txdelta)
+
+ def close(self):
+ assert not self.is_closed
+ self.is_closed = True
+ self.file.close()
+
+
+class TestDirEditor(object):
+ def __init__(self, dir, baseurl, revnum):
+ self.dir = dir
+ self.baseurl = baseurl
+ self.revnum = revnum
+ self.is_closed = False
+ self.children = []
+
+ def close_children(self):
+ for c in reversed(self.children):
+ if not c.is_closed:
+ c.close()
+
+ def close(self):
+ assert not self.is_closed
+ self.is_closed = True
+ self.close_children()
+ self.dir.close()
+
+ def change_prop(self, name, value):
+ self.dir.change_prop(name, value)
+
+ def open_dir(self, path):
+ self.close_children()
+ child = TestDirEditor(self.dir.open_directory(path, -1), self.baseurl, self.revnum)
+ self.children.append(child)
+ return child
+
+ def open_file(self, path):
+ self.close_children()
+ child = TestFileEditor(self.dir.open_file(path, -1))
+ self.children.append(child)
+ return child
+
+ def add_dir(self, path, copyfrom_path=None, copyfrom_rev=-1):
+ self.close_children()
+ if copyfrom_path is not None:
+ copyfrom_path = urlutils.join(self.baseurl, copyfrom_path)
+ if copyfrom_path is not None and copyfrom_rev == -1:
+ copyfrom_rev = self.revnum
+ assert (copyfrom_path is None and copyfrom_rev == -1) or \
+ (copyfrom_path is not None and copyfrom_rev > -1)
+ child = TestDirEditor(self.dir.add_directory(path, copyfrom_path, copyfrom_rev), self.baseurl, self.revnum)
+ self.children.append(child)
+ return child
+
+ def add_file(self, path, copyfrom_path=None, copyfrom_rev=-1):
+ self.close_children()
+ if copyfrom_path is not None:
+ copyfrom_path = urlutils.join(self.baseurl, copyfrom_path)
+ if copyfrom_path is not None and copyfrom_rev == -1:
+ copyfrom_rev = self.revnum
+ child = TestFileEditor(self.dir.add_file(path, copyfrom_path, copyfrom_rev))
+ self.children.append(child)
+ return child
+
+ def delete(self, path):
+ self.dir.delete_entry(path)
+
+
+class TestCommitEditor(TestDirEditor):
+ def __init__(self, editor, baseurl, revnum):
+ self.editor = editor
+ TestDirEditor.__init__(self, self.editor.open_root(), baseurl, revnum)
+
+ def close(self):
+ TestDirEditor.close(self)
+ self.editor.close()
+
+
+class SubversionTestCase(TestCaseInTempDir):
+ """A test case that provides the ability to build Subversion
+ repositories."""
+
+ def setUp(self):
+ super(SubversionTestCase, self).setUp()
+ self.client_ctx = client.Client()
+ self.client_ctx.auth = Auth([ra.get_simple_provider(),
+ ra.get_username_provider(),
+ ra.get_ssl_client_cert_file_provider(),
+ ra.get_ssl_client_cert_pw_file_provider(),
+ ra.get_ssl_server_trust_file_provider()])
+ self.client_ctx.log_msg_func = self.log_message_func
+ #self.client_ctx.notify_func = lambda err: mutter("Error: %s" % err)
+
+ def log_message_func(self, items):
+ return self.next_message
+
+ def make_repository(self, relpath, allow_revprop_changes=True):
+ """Create a repository.
+
+ :return: Handle to the repository.
+ """
+ abspath = os.path.join(self.test_dir, relpath)
+
+ repos.create(abspath)
+
+ if allow_revprop_changes:
+ if sys.platform == 'win32':
+ revprop_hook = os.path.join(abspath, "hooks", "pre-revprop-change.bat")
+ open(revprop_hook, 'w').write("exit 0\n")
+ else:
+ revprop_hook = os.path.join(abspath, "hooks", "pre-revprop-change")
+ open(revprop_hook, 'w').write("#!/bin/sh\n")
+ os.chmod(revprop_hook, os.stat(revprop_hook).st_mode | 0111)
+
+ return urlutils.local_path_to_url(abspath)
+
+
+ def make_checkout(self, repos_url, relpath):
+ self.client_ctx.checkout(repos_url, relpath, "HEAD")
+
+ def client_set_prop(self, path, name, value):
+ if value is None:
+ value = ""
+ self.client_ctx.propset(name, value, path, False, True)
+
+ def client_get_prop(self, path, name, revnum=None, recursive=False):
+ if revnum is None:
+ rev = "WORKING"
+ else:
+ rev = revnum
+ ret = self.client_ctx.propget(name, path, rev, rev, recursive)
+ if recursive:
+ return ret
+ else:
+ return ret.values()[0]
+
+ def client_get_revprop(self, url, revnum, name):
+ r = ra.RemoteAccess(url)
+ return r.rev_proplist(revnum)[name]
+
+ def client_set_revprop(self, url, revnum, name, value):
+ r = ra.RemoteAccess(url)
+ r.change_rev_prop(revnum, name, value)
+
+ def client_commit(self, dir, message=None, recursive=True):
+ """Commit current changes in specified working copy.
+
+ :param relpath: List of paths to commit.
+ """
+ olddir = os.path.abspath('.')
+ self.next_message = message
+ os.chdir(dir)
+ info = self.client_ctx.commit(["."], recursive, False)
+ os.chdir(olddir)
+ assert info is not None
+ return info
+
+ def client_add(self, relpath, recursive=True):
+ """Add specified files to working copy.
+
+ :param relpath: Path to the files to add.
+ """
+ self.client_ctx.add(relpath, recursive, False, False)
+
+ def client_log(self, url, start_revnum, stop_revnum):
+ r = ra.RemoteAccess(url)
+ assert isinstance(url, str)
+ ret = {}
+ def rcvr(orig_paths, rev, revprops, has_children=None):
+ ret[rev] = (orig_paths, revprops.get(properties.PROP_REVISION_AUTHOR), revprops.get(properties.PROP_REVISION_DATE), revprops.get(properties.PROP_REVISION_LOG))
+ r.get_log(rcvr, [""], start_revnum, stop_revnum, 0, True, True,
+ revprops=[properties.PROP_REVISION_AUTHOR, properties.PROP_REVISION_DATE, properties.PROP_REVISION_LOG])
+ return ret
+
+ def client_delete(self, relpath):
+ """Remove specified files from working copy.
+
+ :param relpath: Path to the files to remove.
+ """
+ self.client_ctx.delete([relpath], True)
+
+ def client_copy(self, oldpath, newpath, revnum=None):
+ """Copy file in working copy.
+
+ :param oldpath: Relative path to original file.
+ :param newpath: Relative path to new file.
+ """
+ if revnum is None:
+ rev = "HEAD"
+ else:
+ rev = revnum
+ self.client_ctx.copy(oldpath, newpath, rev)
+
+ def client_update(self, path):
+ self.client_ctx.update([path], "HEAD", True)
+
+ def build_tree(self, files):
+ """Create a directory tree.
+
+ :param files: Dictionary with filenames as keys, contents as
+ values. None as value indicates a directory.
+ """
+ for f in files:
+ if files[f] is None:
+ try:
+ os.makedirs(f)
+ except OSError:
+ pass
+ else:
+ try:
+ os.makedirs(os.path.dirname(f))
+ except OSError:
+ pass
+ open(f, 'w').write(files[f])
+
+ def make_client(self, repospath, clientpath, allow_revprop_changes=True):
+ """Create a repository and a checkout. Return the checkout.
+
+ :param relpath: Optional relpath to check out if not the full
+ repository.
+ :param clientpath: Path to checkout
+ :return: Repository URL.
+ """
+ repos_url = self.make_repository(repospath,
+ allow_revprop_changes=allow_revprop_changes)
+ self.make_checkout(repos_url, clientpath)
+ return repos_url
+
+ def open_fs(self, relpath):
+ """Open a fs.
+
+ :return: FS.
+ """
+ return repos.Repository(relpath).fs()
+
+ def get_commit_editor(self, url, message="Test commit"):
+ ra = RemoteAccess(url.encode("utf-8"))
+ revnum = ra.get_latest_revnum()
+ return TestCommitEditor(ra.get_commit_editor({"svn:log": message}), ra.url, revnum)
=== modified file 'subvertpy/subvertpy/tests/test_client.py'
--- a/subvertpy/subvertpy/tests/test_client.py 2008-10-02 21:16:21 +0000
+++ b/subvertpy/subvertpy/tests/test_client.py 2008-10-06 14:53:19 +0000
@@ -16,7 +16,7 @@
"""Subversion client library tests."""
from subvertpy import client
-from bzrlib.plugins.svn.tests import SubversionTestCase
+from subvertpy.tests import SubversionTestCase
class TestClient(SubversionTestCase):
def setUp(self):
=== added file 'subvertpy/subvertpy/tests/test_marshall.py'
--- a/subvertpy/subvertpy/tests/test_marshall.py 1970-01-01 00:00:00 +0000
+++ b/subvertpy/subvertpy/tests/test_marshall.py 2008-10-06 14:25:30 +0000
@@ -0,0 +1,87 @@
+# Copyright (C) 2006-2007 Jelmer Vernooij <jelmer at samba.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from unittest import TestCase
+from subvertpy.marshall import literal, MarshallError, marshall, unmarshall
+
+class TestMarshalling(TestCase):
+ def test_literal_txt(self):
+ l = literal("foo")
+ self.assertEqual("foo", l.txt)
+
+ def test_literal_str(self):
+ l = literal("foo bar")
+ self.assertEqual("foo bar", l.__str__())
+
+ def test_literal_rep(self):
+ l = literal("foo bar")
+ self.assertEqual("foo bar", l.__repr__())
+
+ def test_marshall_error(self):
+ e = MarshallError("bla bla")
+ self.assertEqual("bla bla", e.__str__())
+
+ def test_marshall_int(self):
+ self.assertEqual("1 ", marshall(1))
+
+ def test_marshall_list(self):
+ self.assertEqual("( 1 2 3 4 ) ", marshall([1,2,3,4]))
+
+ def test_marshall_list_mixed(self):
+ self.assertEqual("( 1 3 4 3:str ) ", marshall([1,3,4,"str"]))
+
+ def test_marshall_literal(self):
+ self.assertEqual("foo ", marshall(literal("foo")))
+
+ def test_marshall_string(self):
+ self.assertEqual("3:foo ", marshall("foo"))
+
+ def test_marshall_raises(self):
+ self.assertRaises(MarshallError, marshall, dict())
+
+ def test_marshall_list_nested(self):
+ self.assertEqual("( ( ( 3 ) 4 ) ) ", marshall([[[3], 4]]))
+
+ def test_marshall_string_space(self):
+ self.assertEqual("5:bla l ", marshall("bla l"))
+
+ def test_unmarshall_string(self):
+ self.assertEqual(('', "bla l"), unmarshall("5:bla l"))
+
+ def test_unmarshall_list(self):
+ self.assertEqual(('', [4,5]), unmarshall("( 4 5 ) "))
+
+ def test_unmarshall_int(self):
+ self.assertEqual(('', 2), unmarshall("2 "))
+
+ def test_unmarshall_literal(self):
+ self.assertEqual(('', literal("x")), unmarshall("x "))
+
+ def test_unmarshall_empty(self):
+ self.assertRaises(MarshallError, unmarshall, "")
+
+ def test_unmarshall_nospace(self):
+ self.assertRaises(MarshallError, unmarshall, "nospace")
+
+ def test_unmarshall_toolong(self):
+ self.assertRaises(MarshallError, unmarshall, "43432432:bla")
+
+ def test_unmarshall_literal(self):
+ self.assertRaises(MarshallError, unmarshall, ":-3213")
+
+ def test_unmarshall_open_list(self):
+ self.assertRaises(MarshallError, unmarshall, "( 3 4 ")
+
=== modified file 'subvertpy/subvertpy/tests/test_ra.py'
--- a/subvertpy/subvertpy/tests/test_ra.py 2008-10-02 21:16:21 +0000
+++ b/subvertpy/subvertpy/tests/test_ra.py 2008-10-06 14:53:19 +0000
@@ -15,9 +15,10 @@
"""Subversion ra library tests."""
+from cStringIO import StringIO
from unittest import TestCase
from subvertpy import ra, SubversionException
-from bzrlib.plugins.svn.tests import SubversionTestCase
+from subvertpy.tests import SubversionTestCase
class VersionTest(TestCase):
def test_version_length(self):
@@ -175,6 +176,18 @@
self.assertEquals("/bar", rets[0][0])
self.assertEquals("/bar", rets[1][0])
+ def test_get_file(self):
+ cb = self.commit_editor()
+ cb.add_file("bar").modify("a")
+ cb.close()
+
+ stream = StringIO()
+
+ self.ra.get_file("bar", stream, 1)
+
+ stream.seek(0)
+ self.assertEquals("a", stream.read())
+
def test_get_locations_root(self):
self.assertEquals({0: "/"}, self.ra.get_locations("", 0, [0]))
More information about the bazaar-commits
mailing list