1
2
3
4 """
5 SVN functionality.
6 """
7
8 import os
9 import commands
10 import re
11
12 from moap.util import util, log
13 from moap.vcs import vcs
14
16 """
17 Detect if the given source tree is using svn.
18
19 @return: True if the given path looks like a Subversion tree.
20 """
21 if not os.path.exists(os.path.join(path, '.svn')):
22 log.debug('svn', 'Did not find .svn directory under %s' % path)
23 return False
24
25 for n in ['props', 'text-base']:
26 if not os.path.exists(os.path.join(path, '.svn', n)):
27 log.debug('svn', 'Did not find .svn/%s under %s' % (n, path))
28 return False
29
30 return True
31
33 name = 'Subversion'
34
35 meta = ['.svn']
36
38 """
39 @param status: one character indicating the status we want to get
40 all paths for.
41 """
42 ret = []
43
44
45 if status == '?':
46 status = '\?'
47
48 oldPath = os.getcwd()
49
50 os.chdir(path)
51 cmd = "svn status --no-ignore"
52 output = commands.getoutput(cmd)
53 lines = output.split("\n")
54 matcher = re.compile('^' + status + '\s+(.*)')
55 for l in lines:
56 m = matcher.search(l)
57 if m:
58 relpath = m.expand("\\1")
59 ret.append(relpath)
60
61
62 os.chdir(oldPath)
63 return ret
64
67
70
73
76
77 - def ignore(self, paths, commit=True):
78 oldPath = os.getcwd()
79
80 os.chdir(self.path)
81
82 tree = self.createTree(paths)
83 toCommit = []
84 for path in tree.keys():
85
86 cmd = "svn propget svn:ignore %s" % path
87 (status, output) = commands.getstatusoutput(cmd)
88 lines = output.split("\n")
89
90
91
92 temp = util.writeTemp(lines + tree[path])
93
94 if path == '':
95 path = '.'
96 toCommit.append(path)
97 cmd = "svn propset svn:ignore --file %s %s" % (temp, path)
98 os.system(cmd)
99 os.unlink(temp)
100
101 if commit and toCommit:
102 cmd = "svn commit -m 'moap ignore' -N %s" % " ".join(toCommit)
103 os.system(cmd)
104 os.chdir(oldPath)
105
106 - def commit(self, paths, message):
107
108 parents = []
109 for p in paths:
110 while p:
111 p = os.path.dirname(p)
112 if p:
113 parents.append(p)
114
115 paths.extend(parents)
116 temp = util.writeTemp([message, ])
117 paths = [os.path.join(self.path, p) for p in paths]
118 cmd = "svn commit --non-recursive --file %s %s" % (
119 temp, " ".join(paths))
120 log.debug('svn', 'Executing command: %s' % cmd)
121 status = os.system(cmd)
122 os.unlink(temp)
123 if status != 0:
124 return False
125
126 return True
127
128 - def diff(self, path):
129
130
131
132
133
134 oldPath = os.getcwd()
135 os.chdir(self.path)
136
137 cmd = "LANG=C svn diff %s" % path
138 output = commands.getoutput(cmd)
139 os.chdir(oldPath)
140
141 return self.scrubPropertyChanges(output)
142
144 """
145 Scrub the given diff output from property changes.
146 """
147 reo = re.compile(
148 '^$\n'
149 '^Property changes on:.*?$\n'
150 '.*?'
151 '^$\n',
152 re.MULTILINE | re.DOTALL)
153
154 return reo.sub('', output)
155
157 ret = {}
158
159 cmd = "LANG=C svn diff %s" % path
160
161
162 output = commands.getoutput(cmd) + '\n'
163
164
165 reo = re.compile(
166 'Property changes on: (.*?)$\n'
167 '^_*$\n'
168 '^(\w*: .*?'
169 '(?:Property)?)'
170 '^$\n'
171 , re.MULTILINE | re.DOTALL)
172
173
174 reop = re.compile(
175 '^\w*: (.*?)\n'
176 , re.MULTILINE | re.DOTALL)
177
178
179 fileMatches = reo.findall(output)
180 for path, properties in fileMatches:
181 ret[path] = reop.findall(properties)
182
183 return ret
184
186 cmd = "svn update %s" % path
187 status, output = commands.getstatusoutput(cmd)
188 if status != 0:
189 raise vcs.VCSException(output)
190 return output
191
193 ret = []
194
195 oldPath = os.getcwd()
196 os.chdir(self.path)
197
198
199 cmd = "svn info %s" % self.path
200 status, output = commands.getstatusoutput(cmd)
201 if status != 0:
202 raise vcs.VCSException(output)
203 lines = output.split('\n')
204 url = None
205 baseRevision = None
206 for line in lines:
207 if line.startswith('URL: '):
208 url = line[4:]
209 if line.startswith('Revision: '):
210 baseRevision = int(line[10:])
211
212 ret.append(
213 'svn checkout --non-interactive --revision %d %s checkout\n' % (
214 baseRevision, url))
215
216
217
218 cmd = "svn status -v"
219 status, output = commands.getstatusoutput(cmd)
220 if status != 0:
221 raise vcs.VCSException(output)
222 lines = output.split('\n')
223
224 matcher = re.compile('.{8}'
225 '\s+(\d+)'
226 '\s+(\d+)'
227 '\s+(\w+)'
228 '\s+(.*)'
229 )
230
231
232 for line in lines:
233 m = matcher.search(line)
234 if m:
235 revision = int(m.expand("\\1"))
236 path = m.expand("\\4")
237 if revision != baseRevision:
238 ret.append('svn update --non-interactive --non-recursive '
239 '--revision %d %s' % (
240 revision, os.path.join('checkout', path)))
241
242 os.chdir(oldPath)
243
244 return "\n".join(ret) + ('\n')
245
246 VCSClass = SVN
247