Fix fetching revisions containing replaced files.
[jelmer/subvertpy.git] / scheme.py
1 # Copyright (C) 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.errors import NotBranchError
18
19 class BranchingScheme:
20     """ Divides SVN repository data up into branches. Since there
21     is no proper way to do this, there are several subclasses of this class
22     each of which handles a particular convention that may be in use.
23     """
24     def is_branch(self, path):
25         """Check whether a location refers to a branch.
26         
27         :param path: Path to check.
28         """
29         raise NotImplementedError
30
31     def unprefix(self, path):
32         """Split up a Subversion path into a branch-path and inside-branch path.
33
34         :param path: Path to split up.
35         :return: Tuple with branch-path and inside-branch path.
36         """
37         raise NotImplementedError
38
39     @staticmethod
40     def guess_scheme(relpath):
41         """Try to guess the branching scheme based on a partial URL.
42
43         :param relpath: Relative URL to a branch.
44         :return: New BranchingScheme instance.
45         """
46         parts = relpath.strip("/").split("/")
47         for i in range(0,len(parts)):
48             if parts[i] == "trunk" or \
49                parts[i] == "branches" or \
50                parts[i] == "tags":
51                 return TrunkBranchingScheme(level=i)
52
53         return NoBranchingScheme()
54                 
55
56 class TrunkBranchingScheme:
57     def __init__(self, level=0):
58         self.level = level
59
60     def is_branch(self, path):
61         """See BranchingScheme.is_branch()."""
62         parts = path.strip("/").split("/")
63         if len(parts) == self.level+1 and parts[self.level] == "trunk":
64             return True
65
66         if len(parts) == self.level+2 and \
67            (parts[self.level] == "branches" or parts[self.level] == "tags"):
68             return True
69
70         return False
71
72     def unprefix(self, path):
73         """See BranchingScheme.unprefix()."""
74         parts = path.strip("/").split("/")
75         if len(parts) == 0 or self.level >= len(parts):
76             raise NotBranchError(path=path)
77
78         if parts[self.level] == "trunk" or parts[self.level] == "hooks":
79             return ("/".join(parts[0:self.level+1]).strip("/"), 
80                     "/".join(parts[self.level+1:]).strip("/"))
81         elif parts[self.level] == "tags" or parts[self.level] == "branches":
82             return ("/".join(parts[0:self.level+2]).strip("/"), 
83                     "/".join(parts[self.level+2:]).strip("/"))
84         else:
85             raise NotBranchError(path=path)
86
87     def __str__(self):
88         return "trunk%d" % self.level
89
90
91 class NoBranchingScheme:
92     def is_branch(self, path):
93         """See BranchingScheme.is_branch()."""
94         return path.strip("/") == ""
95
96     def unprefix(self, path):
97         """See BranchingScheme.unprefix()."""
98         return ("", path.strip("/"))
99
100     def __str__(self):
101         return "null"
102
103
104 class ListBranchingScheme:
105     def __init__(self, branch_list):
106         """Create new ListBranchingScheme instance.
107
108         :param branch_list: List of know branch locations.
109         """
110         self.branch_list = []
111         for p in branch_list:
112             self.branch_list.append(p.strip("/"))
113
114     def is_branch(self, path):
115         """See BranchingScheme.is_branch()."""
116         return path.strip("/") in self.branch_list
117
118     def unprefix(self, path):
119         """See BranchingScheme.unprefix()."""
120         path = path.strip("/")
121         for i in self.branch_list:
122             if (path+"/").startswith(i+"/"):
123                 return (i, path[len(i):].strip("/"))
124
125         raise NotBranchError(path=path)