Move logwalker into a separate file, integrate svntest.
[jelmer/subvertpy.git] / branch.py
1 # Copyright (C) 2005-2006 Jelmer Vernooij <jelmer@samba.org>
2
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17 from bzrlib.branch import Branch, BranchFormat, BranchCheckResult, BzrBranch
18 from bzrlib.delta import compare_trees
19 from bzrlib.errors import (NotBranchError, NoWorkingTree, NoSuchRevision, 
20                            NoSuchFile)
21 from bzrlib.inventory import (Inventory, InventoryFile, InventoryDirectory, 
22                               ROOT_ID)
23 from bzrlib.revision import Revision, NULL_REVISION
24 from bzrlib.tree import Tree, EmptyTree
25 from bzrlib.trace import mutter, note
26 from bzrlib.workingtree import WorkingTree
27
28 import os
29
30 import svn.core, svn.ra
31 from svn.core import SubversionException
32
33 svn.ra.initialize()
34
35 class FakeControlFiles(object):
36     def get_utf8(self, name):
37         raise NoSuchFile(name)
38
39
40 class SvnBranch(Branch):
41     """Maps to a Branch in a Subversion repository """
42     def __init__(self, repos, branch_path):
43         """Instantiate a new SvnBranch.
44
45         :param repos: SvnRepository this branch is part of.
46         :param branch_path: Relative path inside the repository this
47             branch is located at.
48         """
49         self.repository = repos
50         self.branch_path = branch_path
51         self.control_files = FakeControlFiles()
52         self._generate_revision_history()
53         self.base = "%s/%s" % (repos.url, branch_path)
54         self._format = SvnBranchFormat()
55         mutter("Connected to branch at %s" % branch_path)
56
57     def check(self):
58         """See Branch.Check.
59
60         Doesn't do anything for Subversion repositories at the moment (yet).
61         """
62         return BranchCheckResult(self)
63         
64     def _generate_revision_history(self):
65         def rcvr(paths, rev):
66             return self.repository.generate_revision_id(rev, self.branch_path)
67         self._revision_history = map(rcvr, 
68                 self.repository._log.follow_history(self.branch_path, self.repository.latest_revnum))
69
70     def set_root_id(self, file_id):
71         raise NotImplementedError(self.set_root_id)
72             
73     def get_root_id(self):
74         inv = self.repository.get_inventory(self.last_revision())
75         return inv.root.file_id
76
77     def _get_nick(self):
78         return self.branch_path
79
80     nick = property(_get_nick)
81
82     def abspath(self, name):
83         return self.base+"/"+name
84
85     def push_stores(self, branch_to):
86         raise NotImplementedError(self.push_stores)
87
88     def get_revision_inventory(self, revision_id):
89         raise NotImplementedError(self.get_revision_inventory)
90
91     def sign_revision(self, revision_id, gpg_strategy):
92         raise NotImplementedError(self.sign_revision)
93
94     def store_revision_signature(self, gpg_strategy, plaintext, revision_id):
95         raise NotImplementedError(self.store_revision_signature)
96
97     def set_revision_history(self, rev_history):
98         raise NotImplementedError(self.set_revision_history)
99
100     def set_push_location(self, location):
101         raise NotImplementedError(self.set_push_location)
102
103     def get_push_location(self):
104         # get_push_location not supported on Subversion
105         return None
106
107     def revision_history(self):
108         return self._revision_history
109
110     def pull(self, source, overwrite=False):
111         raise NotImplementedError(self.pull)
112
113     def update_revisions(self, other, stop_revision=None):
114         raise NotImplementedError(self.update_revisions)
115
116     def pullable_revisions(self, other, stop_revision):
117         raise NotImplementedError(self.pullable_revisions)
118         
119     # The remote server handles all this for us
120     def lock_write(self):
121         pass
122         
123     def lock_read(self):
124         pass
125
126     def unlock(self):
127         pass
128
129     def get_parent(self):
130         return None
131
132     def set_parent(self, url):
133         raise NotImplementedError(self.set_parent, 
134                                   'can not change parent of SVN branch')
135
136     def get_transaction(self):
137         raise NotImplementedError(self.get_transaction)
138
139     def append_revision(self, *revision_ids):
140         # FIXME: raise NotImplementedError(self.append_revision)
141         pass
142
143     def get_physical_lock_status(self):
144         return False
145
146     def sprout(self, to_bzrdir, revision_id=None):
147         result = BranchFormat.get_default_format().initialize(to_bzrdir)
148         self.copy_content_into(result, revision_id=revision_id)
149         result.set_parent(self.bzrdir.root_transport.base)
150         return result
151
152     def copy_content_into(self, destination, revision_id=None):
153         new_history = self.revision_history()
154         if revision_id is not None:
155             try:
156                 new_history = new_history[:new_history.index(revision_id) + 1]
157             except ValueError:
158                 rev = self.repository.get_revision(revision_id)
159                 new_history = rev.get_history(self.repository)[1:]
160         destination.set_revision_history(new_history)
161         parent = self.get_parent()
162         if parent:
163             destination.set_parent(parent)
164
165
166 class SvnBranchFormat(BranchFormat):
167     """ Branch format for Subversion Branches."""
168     def __init__(self):
169         BranchFormat.__init__(self)
170
171     def get_format_description(self):
172         """See Branch.get_format_description."""
173         return 'Subversion Smart Server'
174
175     def get_format_string(self):
176         return 'Subversion Smart Server'
177
178     def initialize(self, to_bzrdir):
179         raise NotImplementedError(self.initialize)
180