Gentoo Archives: gentoo-commits

From: Brian Dolbec <dolsen@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:repoman commit in: pym/repoman/modules/vcs/, pym/repoman/modules/vcs/bzr/, pym/repoman/, ...
Date: Sun, 31 Jan 2016 20:04:05
Message-Id: 1454270332.bf8493a23aba0e0ce83a16dab5be1e26b835f4b0.dolsen@gentoo
1 commit: bf8493a23aba0e0ce83a16dab5be1e26b835f4b0
2 Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
3 AuthorDate: Sat Jan 30 01:58:36 2016 +0000
4 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
5 CommitDate: Sun Jan 31 19:58:52 2016 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=bf8493a2
7
8 repoman: Migrate actions.py vcs code to the vcs modules
9
10 Add missing changes code to the existing Changes classes.
11 This removes the duplicated code in the Actions class.
12 It alsosspeeds up the run by not calling the vcs binary to scan for changes a second time.
13 Optimize the code for the vcs modules.
14
15 sdfgsdf
16
17 pym/repoman/actions.py | 208 ++++---------------------------
18 pym/repoman/modules/vcs/None/__init__.py | 1 +
19 pym/repoman/modules/vcs/bzr/__init__.py | 1 +
20 pym/repoman/modules/vcs/bzr/changes.py | 21 +++-
21 pym/repoman/modules/vcs/changes.py | 29 +++++
22 pym/repoman/modules/vcs/cvs/__init__.py | 1 +
23 pym/repoman/modules/vcs/cvs/changes.py | 29 +++--
24 pym/repoman/modules/vcs/git/__init__.py | 1 +
25 pym/repoman/modules/vcs/git/changes.py | 26 ++--
26 pym/repoman/modules/vcs/hg/__init__.py | 1 +
27 pym/repoman/modules/vcs/hg/changes.py | 40 +++++-
28 pym/repoman/modules/vcs/settings.py | 5 +-
29 pym/repoman/modules/vcs/svn/__init__.py | 1 +
30 pym/repoman/modules/vcs/svn/changes.py | 38 +++++-
31 14 files changed, 185 insertions(+), 217 deletions(-)
32
33 diff --git a/pym/repoman/actions.py b/pym/repoman/actions.py
34 index 3fd940c..d7f343b 100644
35 --- a/pym/repoman/actions.py
36 +++ b/pym/repoman/actions.py
37 @@ -16,7 +16,6 @@ from itertools import chain
38 from _emerge.UserQuery import UserQuery
39
40 import portage
41 -from portage import cvstree
42 from portage import os
43 from portage import _encodings
44 from portage import _unicode_encode
45 @@ -26,8 +25,7 @@ from portage.package.ebuild.digestgen import digestgen
46 from portage.process import find_binary, spawn
47 from portage.util import writemsg_level
48
49 -from repoman._subprocess import repoman_popen, repoman_getstatusoutput
50 -from repoman.errors import err
51 +from repoman._subprocess import repoman_getstatusoutput
52 from repoman.gpg import gpgsign, need_signature
53 from repoman import utilities
54 from repoman.modules.vcs.vcs import vcs_files_to_cps
55 @@ -71,13 +69,11 @@ class Actions(object):
56
57
58 def perform(self, qa_output):
59 - myunadded, mydeleted = self._vcs_unadded()
60 + myautoadd = self._vcs_autoadd()
61
62 - myautoadd = self._vcs_autoadd(myunadded)
63 + self._vcs_deleted()
64
65 - self._vcs_deleted(mydeleted)
66 -
67 - changes = self.get_vcs_changed(mydeleted)
68 + changes = self.get_vcs_changed()
69
70 mynew, mychanged, myremoved, no_expansion, expansion = changes
71
72 @@ -127,8 +123,8 @@ class Actions(object):
73
74 print("* %s files being committed..." % green(str(len(myupdates))), end=' ')
75
76 - if self.vcs_settings.vcs not in ('cvs', 'svn'):
77 - # With git, bzr and hg, there's never any keyword expansion, so
78 + if self.vcs_settings.needs_keyword_expansion:
79 + # With some VCS types there's never any keyword expansion, so
80 # there's no need to regenerate manifests and all files will be
81 # committed in one big commit at the end.
82 print()
83 @@ -261,62 +257,8 @@ class Actions(object):
84 sys.exit(1)
85
86
87 - def _vcs_unadded(self):
88 - myunadded = []
89 - mydeleted = []
90 - if self.vcs_settings.vcs == "cvs":
91 - try:
92 - myvcstree = portage.cvstree.getentries("./", recursive=1)
93 - myunadded = portage.cvstree.findunadded(
94 - myvcstree, recursive=1, basedir="./")
95 - except SystemExit:
96 - raise # TODO propagate this
97 - except:
98 - err("Error retrieving CVS tree; exiting.")
99 - if self.vcs_settings.vcs == "svn":
100 - try:
101 - with repoman_popen("svn status --no-ignore") as f:
102 - svnstatus = f.readlines()
103 - myunadded = [
104 - "./" + elem.rstrip().split()[1]
105 - for elem in svnstatus
106 - if elem.startswith("?") or elem.startswith("I")]
107 - except SystemExit:
108 - raise # TODO propagate this
109 - except:
110 - err("Error retrieving SVN info; exiting.")
111 - if self.vcs_settings.vcs == "git":
112 - # get list of files not under version control or missing
113 - myf = repoman_popen("git ls-files --others")
114 - myunadded = ["./" + elem[:-1] for elem in myf]
115 - myf.close()
116 - if self.vcs_settings.vcs == "bzr":
117 - try:
118 - with repoman_popen("bzr status -S .") as f:
119 - bzrstatus = f.readlines()
120 - myunadded = [
121 - "./" + elem.rstrip().split()[1].split('/')[-1:][0]
122 - for elem in bzrstatus
123 - if elem.startswith("?") or elem[0:2] == " D"]
124 - except SystemExit:
125 - raise # TODO propagate this
126 - except:
127 - err("Error retrieving bzr info; exiting.")
128 - if self.vcs_settings.vcs == "hg":
129 - with repoman_popen("hg status --no-status --unknown .") as f:
130 - myunadded = f.readlines()
131 - myunadded = ["./" + elem.rstrip() for elem in myunadded]
132 -
133 - # Mercurial doesn't handle manually deleted files as removed from
134 - # the repository, so the user need to remove them before commit,
135 - # using "hg remove [FILES]"
136 - with repoman_popen("hg status --no-status --deleted .") as f:
137 - mydeleted = f.readlines()
138 - mydeleted = ["./" + elem.rstrip() for elem in mydeleted]
139 - return myunadded, mydeleted
140 -
141 -
142 - def _vcs_autoadd(self, myunadded):
143 + def _vcs_autoadd(self):
144 + myunadded = self.vcs_settings.changes.unadded
145 myautoadd = []
146 if myunadded:
147 for x in range(len(myunadded) - 1, -1, -1):
148 @@ -348,137 +290,35 @@ class Actions(object):
149 return myautoadd
150
151
152 - def _vcs_deleted(self, mydeleted):
153 - if self.vcs_settings.vcs == "hg" and mydeleted:
154 + def _vcs_deleted(self):
155 + if self.vcs_settings.changes.has_deleted:
156 print(red(
157 "!!! The following files are removed manually"
158 " from your local tree but are not"))
159 print(red(
160 "!!! removed from the repository."
161 - " Please remove them, using \"hg remove [FILES]\"."))
162 - for x in mydeleted:
163 + " Please remove them, using \"%s remove [FILES]\"."
164 + % self.vcs_settings.vcs))
165 + for x in self.vcs_settings.changes.deleted:
166 print(" ", x)
167 print()
168 print()
169 sys.exit(1)
170
171
172 - def get_vcs_changed(self, mydeleted):
173 + def get_vcs_changed(self):
174 '''Holding function which calls the approriate VCS module for the data'''
175 - changed = ([], [], [], [], [])
176 - if self.vcs_settings.vcs:
177 - vcs_module = getattr(self, '_get_changed_%s_' % self.vcs_settings.vcs)
178 - changed = vcs_module(mydeleted)
179 - mynew, mychanged, myremoved, no_expansion, expansion = changed
180 -
181 - a_file_is_changed = mychanged or mynew or myremoved
182 - a_file_is_deleted_hg = self.vcs_settings.vcs == "hg" and mydeleted
183 -
184 - if not (a_file_is_changed or a_file_is_deleted_hg):
185 - utilities.repoman_sez(
186 - "\"Doing nothing is not always good for QA.\"")
187 - print()
188 - print("(Didn't find any changed files...)")
189 - print()
190 - sys.exit(1)
191 - return changed
192 -
193 -
194 - def _get_changed_cvs_(self, mydeleted):
195 - mycvstree = cvstree.getentries("./", recursive=1)
196 - mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./")
197 - mynew = cvstree.findnew(mycvstree, recursive=1, basedir="./")
198 - myremoved = portage.cvstree.findremoved(mycvstree, recursive=1, basedir="./")
199 - bin_blob_pattern = re.compile("^-kb$")
200 - no_expansion = set(portage.cvstree.findoption(
201 - mycvstree, bin_blob_pattern, recursive=1, basedir="./"))
202 - expansion = {}
203 - return (mynew, mychanged, myremoved, no_expansion, expansion)
204 -
205 - def _get_changed_svn_(self, mydeleted):
206 - with repoman_popen("svn status") as f:
207 - svnstatus = f.readlines()
208 - mychanged = [
209 - "./" + elem.split()[-1:][0]
210 - for elem in svnstatus
211 - if (elem[:1] in "MR" or elem[1:2] in "M")]
212 - mynew = [
213 - "./" + elem.split()[-1:][0]
214 - for elem in svnstatus
215 - if elem.startswith("A")]
216 - myremoved = [
217 - "./" + elem.split()[-1:][0]
218 - for elem in svnstatus
219 - if elem.startswith("D")]
220 - # Subversion expands keywords specified in svn:keywords properties.
221 - with repoman_popen("svn propget -R svn:keywords") as f:
222 - props = f.readlines()
223 - expansion = dict(
224 - ("./" + prop.split(" - ")[0], prop.split(" - ")[1].split())
225 - for prop in props if " - " in prop)
226 - no_expansion = set()
227 - return (mynew, mychanged, myremoved, no_expansion, expansion)
228 -
229 - def _get_changed_git_(self, mydeleted):
230 - with repoman_popen(
231 - "git diff-index --name-only "
232 - "--relative --diff-filter=M HEAD") as f:
233 - mychanged = f.readlines()
234 - mychanged = ["./" + elem[:-1] for elem in mychanged]
235 - with repoman_popen(
236 - "git diff-index --name-only "
237 - "--relative --diff-filter=A HEAD") as f:
238 - mynew = f.readlines()
239 - mynew = ["./" + elem[:-1] for elem in mynew]
240 - with repoman_popen(
241 - "git diff-index --name-only "
242 - "--relative --diff-filter=D HEAD") as f:
243 - myremoved = f.readlines()
244 - myremoved = ["./" + elem[:-1] for elem in myremoved]
245 - no_expansion = set()
246 - expansion = {}
247 - return (mynew, mychanged, myremoved, no_expansion, expansion)
248 -
249 - def _get_changed_bzr_(self, mydeleted):
250 - with repoman_popen("bzr status -S .") as f:
251 - bzrstatus = f.readlines()
252 - mychanged = [
253 - "./" + elem.split()[-1:][0].split('/')[-1:][0]
254 - for elem in bzrstatus
255 - if elem and elem[1:2] == "M"]
256 - mynew = [
257 - "./" + elem.split()[-1:][0].split('/')[-1:][0]
258 - for elem in bzrstatus
259 - if elem and (elem[1:2] in "NK" or elem[0:1] == "R")]
260 - myremoved = [
261 - "./" + elem.split()[-1:][0].split('/')[-1:][0]
262 - for elem in bzrstatus
263 - if elem.startswith("-")]
264 - myremoved = [
265 - "./" + elem.split()[-3:-2][0].split('/')[-1:][0]
266 - for elem in bzrstatus
267 - if elem and (elem[1:2] == "K" or elem[0:1] == "R")]
268 - # Bazaar expands nothing.
269 - no_expansion = set()
270 - expansion = {}
271 - return (mynew, mychanged, myremoved, no_expansion, expansion)
272 -
273 - def _get_changed_hg_(self, mydeleted):
274 - with repoman_popen("hg status --no-status --modified .") as f:
275 - mychanged = f.readlines()
276 - mychanged = ["./" + elem.rstrip() for elem in mychanged]
277 -
278 - with repoman_popen("hg status --no-status --added .") as f:
279 - mynew = f.readlines()
280 - mynew = ["./" + elem.rstrip() for elem in mynew]
281 -
282 - with repoman_popen("hg status --no-status --removed .") as f:
283 - myremoved = f.readlines()
284 - myremoved = ["./" + elem.rstrip() for elem in myremoved]
285 - no_expansion = set()
286 - expansion = {}
287 - return (mynew, mychanged, myremoved, no_expansion, expansion)
288 + changes = self.vcs_settings.changes
289
290 + if not changes.has_changes:
291 + utilities.repoman_sez(
292 + "\"Doing nothing is not always good for QA.\"")
293 + print()
294 + print("(Didn't find any changed files...)")
295 + print()
296 + sys.exit(1)
297 + return (changes.new, changes.changed, changes.removed,
298 + changes.no_expansion, changes.expansion)
299
300 def get_commit_footer(self):
301 portage_version = getattr(portage, "VERSION", None)
302
303 diff --git a/pym/repoman/modules/vcs/None/__init__.py b/pym/repoman/modules/vcs/None/__init__.py
304 index 4146e1e..2859325 100644
305 --- a/pym/repoman/modules/vcs/None/__init__.py
306 +++ b/pym/repoman/modules/vcs/None/__init__.py
307 @@ -19,6 +19,7 @@ module_spec = {
308 'func_desc': {
309 },
310 'vcs_preserves_mtime': False,
311 + 'needs_keyword_expansion': False,
312 },
313 'None-changes': {
314 'name': "None_changes",
315
316 diff --git a/pym/repoman/modules/vcs/bzr/__init__.py b/pym/repoman/modules/vcs/bzr/__init__.py
317 index ccdbddf..1192782 100644
318 --- a/pym/repoman/modules/vcs/bzr/__init__.py
319 +++ b/pym/repoman/modules/vcs/bzr/__init__.py
320 @@ -19,6 +19,7 @@ module_spec = {
321 'func_desc': {
322 },
323 'vcs_preserves_mtime': True,
324 + 'needs_keyword_expansion': False,
325 },
326 'bzr-changes': {
327 'name': "bzr_changes",
328
329 diff --git a/pym/repoman/modules/vcs/bzr/changes.py b/pym/repoman/modules/vcs/bzr/changes.py
330 index 0f70613..41ce347 100644
331 --- a/pym/repoman/modules/vcs/bzr/changes.py
332 +++ b/pym/repoman/modules/vcs/bzr/changes.py
333 @@ -25,8 +25,19 @@ class Changes(ChangesBase):
334 "./" + elem.split()[-1:][0].split('/')[-1:][0]
335 for elem in bzrstatus
336 if elem and (elem[1:2] == "NK" or elem[0:1] == "R")]
337 - if self.options.if_modified == "y":
338 - self.removed = [
339 - "./" + elem.split()[-3:-2][0].split('/')[-1:][0]
340 - for elem in bzrstatus
341 - if elem and (elem[1:2] == "K" or elem[0:1] == "R")]
342 + self.removed = [
343 + "./" + elem.split()[-3:-2][0].split('/')[-1:][0]
344 + for elem in bzrstatus
345 + if elem and (elem[1:2] == "K" or elem[0:1] == "R")]
346 + # Bazaar expands nothing.
347 +
348 + @property
349 + def unadded(self):
350 + '''Bazzar method of getting the unadded files in the repository'''
351 + if self._unadded is not None:
352 + return self._unadded
353 + self._unadded = [
354 + "./" + elem.rstrip().split()[1].split('/')[-1:][0]
355 + for elem in bzrstatus
356 + if elem.startswith("?") or elem[0:2] == " D"]
357 + return self._unadded
358
359 diff --git a/pym/repoman/modules/vcs/changes.py b/pym/repoman/modules/vcs/changes.py
360 index 6553ac9..6eefaed 100644
361 --- a/pym/repoman/modules/vcs/changes.py
362 +++ b/pym/repoman/modules/vcs/changes.py
363 @@ -21,6 +21,10 @@ class ChangesBase(object):
364 self.changed = []
365 self.new = []
366 self.removed = []
367 + self.no_expansion = set()
368 + self._expansion = None
369 + self._deleted = None
370 + self._unadded = None
371
372 def scan(self):
373 self._reset()
374 @@ -37,3 +41,28 @@ class ChangesBase(object):
375 '''Placeholder for subclassing'''
376 pass
377
378 + @property
379 + def has_deleted(self):
380 + '''Placeholder for VCS that requires manual deletion of files'''
381 + return self.deleted != []
382 +
383 + @property
384 + def has_changes(self):
385 + '''Placeholder for VCS repo common has changes result'''
386 + changed = self.changed or self.new or self.removed or self.deleted
387 + return changed != []
388 +
389 + @property
390 + def unadded(self):
391 + '''Override this function as needed'''
392 + return []
393 +
394 + @property
395 + def deleted(self):
396 + '''Override this function as needed'''
397 + return []
398 +
399 + @property
400 + def expansion(self):
401 + '''Override this function as needed'''
402 + return {}
403
404 diff --git a/pym/repoman/modules/vcs/cvs/__init__.py b/pym/repoman/modules/vcs/cvs/__init__.py
405 index 6db6078..ba60e2c 100644
406 --- a/pym/repoman/modules/vcs/cvs/__init__.py
407 +++ b/pym/repoman/modules/vcs/cvs/__init__.py
408 @@ -19,6 +19,7 @@ module_spec = {
409 'func_desc': {
410 },
411 'vcs_preserves_mtime': True,
412 + 'needs_keyword_expansion': True,
413 },
414 'cvs-changes': {
415 'name': "cvs_changes",
416
417 diff --git a/pym/repoman/modules/vcs/cvs/changes.py b/pym/repoman/modules/vcs/cvs/changes.py
418 index f0893a1..cdfb4b2 100644
419 --- a/pym/repoman/modules/vcs/cvs/changes.py
420 +++ b/pym/repoman/modules/vcs/cvs/changes.py
421 @@ -1,7 +1,11 @@
422
423
424 -from portage import cvstree
425 +import re
426 +
427 +from repoman._portage import portage
428 from repoman.modules.vcs.changes import ChangesBase
429 +from portage import cvstree
430 +
431
432 class Changes(ChangesBase):
433 '''Class object to scan and hold the resultant data
434 @@ -12,11 +16,22 @@ class Changes(ChangesBase):
435
436 def __init__(self, options):
437 super(Changes, self).__init__(options)
438 + self._tree = None
439
440 def _scan(self):
441 - tree = cvstree.getentries("./", recursive=1)
442 - self.changed = cvstree.findchanged(tree, recursive=1, basedir="./")
443 - self.new = cvstree.findnew(tree, recursive=1, basedir="./")
444 - if self.options.if_modified == "y":
445 - self.removed = cvstree.findremoved(tree, recursive=1, basedir="./")
446 - del tree
447 + '''VCS type scan function, looks for all detectable changes'''
448 + self._tree = portage.cvstree.getentries("./", recursive=1)
449 + self.changed = cvstree.findchanged(self._tree, recursive=1, basedir="./")
450 + self.new = cvstree.findnew(self._tree, recursive=1, basedir="./")
451 + self.removed = cvstree.findremoved(self._tree, recursive=1, basedir="./")
452 + bin_blob_pattern = re.compile("^-kb$")
453 + self.no_expansion = set(portage.cvstree.findoption(
454 + self._tree, bin_blob_pattern, recursive=1, basedir="./"))
455 +
456 + @property
457 + def unadded(self):
458 + '''VCS method of getting the unadded files in the repository'''
459 + if self._unadded is not None:
460 + return self._unadded
461 + self._unadded = portage.cvstree.findunadded(self._tree, recursive=1, basedir="./")
462 + return self._unadded
463
464 diff --git a/pym/repoman/modules/vcs/git/__init__.py b/pym/repoman/modules/vcs/git/__init__.py
465 index 4e1d599..e077767 100644
466 --- a/pym/repoman/modules/vcs/git/__init__.py
467 +++ b/pym/repoman/modules/vcs/git/__init__.py
468 @@ -19,6 +19,7 @@ module_spec = {
469 'func_desc': {
470 },
471 'vcs_preserves_mtime': False,
472 + 'needs_keyword_expansion': False,
473 },
474 'git-changes': {
475 'name': "git_changes",
476
477 diff --git a/pym/repoman/modules/vcs/git/changes.py b/pym/repoman/modules/vcs/git/changes.py
478 index 6ee39a0..0342251 100644
479 --- a/pym/repoman/modules/vcs/git/changes.py
480 +++ b/pym/repoman/modules/vcs/git/changes.py
481 @@ -27,11 +27,23 @@ class Changes(ChangesBase):
482 "--relative --diff-filter=A HEAD") as f:
483 new = f.readlines()
484 self.new = ["./" + elem[:-1] for elem in new]
485 - if self.options.if_modified == "y":
486 - with repoman_popen(
487 - "git diff-index --name-only "
488 - "--relative --diff-filter=D HEAD") as f:
489 - removed = f.readlines()
490 - self.removed = ["./" + elem[:-1] for elem in removed]
491 - del removed
492 + del new
493
494 + with repoman_popen(
495 + "git diff-index --name-only "
496 + "--relative --diff-filter=D HEAD") as f:
497 + removed = f.readlines()
498 + self.removed = ["./" + elem[:-1] for elem in removed]
499 + del removed
500 +
501 + @property
502 + def unadded(self):
503 + '''VCS method of getting the unadded files in the repository'''
504 + if self._unadded is not None:
505 + return self._unadded
506 + # get list of files not under version control or missing
507 + with repoman_popen("git ls-files --others") as f:
508 + unadded = f.readlines()
509 + self._unadded = ["./" + elem[:-1] for elem in unadded]
510 + del unadded
511 + return self._unadded
512
513 diff --git a/pym/repoman/modules/vcs/hg/__init__.py b/pym/repoman/modules/vcs/hg/__init__.py
514 index 6f8a376..6737dfb 100644
515 --- a/pym/repoman/modules/vcs/hg/__init__.py
516 +++ b/pym/repoman/modules/vcs/hg/__init__.py
517 @@ -19,6 +19,7 @@ module_spec = {
518 'func_desc': {
519 },
520 'vcs_preserves_mtime': False,
521 + 'needs_keyword_expansion': False,
522 },
523 'hg-changes': {
524 'name': "hg_changes",
525
526 diff --git a/pym/repoman/modules/vcs/hg/changes.py b/pym/repoman/modules/vcs/hg/changes.py
527 index 86dffff..f4e1ec8 100644
528 --- a/pym/repoman/modules/vcs/hg/changes.py
529 +++ b/pym/repoman/modules/vcs/hg/changes.py
530 @@ -18,12 +18,40 @@ class Changes(ChangesBase):
531 with repoman_popen("hg status --no-status --modified .") as f:
532 changed = f.readlines()
533 self.changed = ["./" + elem.rstrip() for elem in changed]
534 + del changed
535 +
536 with repoman_popen("hg status --no-status --added .") as f:
537 new = f.readlines()
538 self.new = ["./" + elem.rstrip() for elem in new]
539 - if self.options.if_modified == "y":
540 - with repoman_popen("hg status --no-status --removed .") as f:
541 - removed = f.readlines()
542 - self.removed = ["./" + elem.rstrip() for elem in removed]
543 - del removed
544 - del changed, new
545 + del new
546 +
547 + with repoman_popen("hg status --no-status --removed .") as f:
548 + removed = f.readlines()
549 + self.removed = ["./" + elem.rstrip() for elem in removed]
550 + del removed
551 +
552 + @property
553 + def unadded(self):
554 + '''VCS method of getting the unadded files in the repository'''
555 + if self._unadded is not None:
556 + return self._unadded
557 + with repoman_popen("hg status --no-status --unknown .") as f:
558 + unadded = f.readlines()
559 + self._unadded = ["./" + elem.rstrip() for elem in unadded]
560 + del unadded
561 + return self._unadded
562 +
563 + @property
564 + def deleted(self):
565 + '''VCS method of getting the deleted files in the repository'''
566 + if self._deleted is not None:
567 + return self._deleted
568 + # Mercurial doesn't handle manually deleted files as removed from
569 + # the repository, so the user need to remove them before commit,
570 + # using "hg remove [FILES]"
571 + with repoman_popen("hg status --no-status --deleted .") as f:
572 + deleted = f.readlines()
573 + self._deleted = ["./" + elem.rstrip() for elem in deleted]
574 + del deleted
575 + return self._deleted
576 +
577
578 diff --git a/pym/repoman/modules/vcs/settings.py b/pym/repoman/modules/vcs/settings.py
579 index 34f1c78..bcd5f18 100644
580 --- a/pym/repoman/modules/vcs/settings.py
581 +++ b/pym/repoman/modules/vcs/settings.py
582 @@ -4,7 +4,6 @@ from __future__ import print_function, unicode_literals
583 import logging
584 import sys
585
586 -from repoman._portage import portage
587 from portage.output import red
588 from repoman.modules.vcs import module_controller, module_names
589 from repoman.modules.vcs.vcs import FindVCS
590 @@ -58,6 +57,8 @@ class VCSSettings(object):
591 logging.error("VCSSettings: Unknown VCS type: %s", self.vcs)
592 logging.error("Available modules: %s", module_controller.parents)
593
594 + self.needs_keyword_expansion = module_controller.modules[
595 + "%s_status" % self.vcs]['needs_keyword_expansion']
596 self.vcs_local_opts = repoman_settings.get(
597 "REPOMAN_VCS_LOCAL_OPTS", "").split()
598 self.vcs_global_opts = repoman_settings.get(
599 @@ -88,5 +89,5 @@ class VCSSettings(object):
600 def changes(self):
601 if not self._changes:
602 changes = self.module_controller.get_class('%s_changes' % self.vcs)
603 - self._changes = changes(self.options)
604 + self._changes = changes(self.options, self.vcs)
605 return self._changes
606
607 diff --git a/pym/repoman/modules/vcs/svn/__init__.py b/pym/repoman/modules/vcs/svn/__init__.py
608 index 41e481a..becb93e 100644
609 --- a/pym/repoman/modules/vcs/svn/__init__.py
610 +++ b/pym/repoman/modules/vcs/svn/__init__.py
611 @@ -19,6 +19,7 @@ module_spec = {
612 'func_desc': {
613 },
614 'vcs_preserves_mtime': False,
615 + 'needs_keyword_expansion': True,
616 },
617 'svn-changes': {
618 'name': "svn_changes",
619
620 diff --git a/pym/repoman/modules/vcs/svn/changes.py b/pym/repoman/modules/vcs/svn/changes.py
621 index 3567b61..639ee9f 100644
622 --- a/pym/repoman/modules/vcs/svn/changes.py
623 +++ b/pym/repoman/modules/vcs/svn/changes.py
624 @@ -25,9 +25,35 @@ class Changes(ChangesBase):
625 "./" + elem.split()[-1:][0]
626 for elem in svnstatus
627 if elem.startswith("A")]
628 - if self.options.if_modified == "y":
629 - self.removed = [
630 - "./" + elem.split()[-1:][0]
631 - for elem in svnstatus
632 - if elem.startswith("D")]
633 -
634 + self.removed = [
635 + "./" + elem.split()[-1:][0]
636 + for elem in svnstatus
637 + if elem.startswith("D")]
638 +
639 + @property
640 + def expansion(self):
641 + '''VCS method of getting the expanded keywords in the repository'''
642 + if self._expansion is not None:
643 + return self._expansion
644 + # Subversion expands keywords specified in svn:keywords properties.
645 + with repoman_popen("svn propget -R svn:keywords") as f:
646 + props = f.readlines()
647 + self._expansion = dict(
648 + ("./" + prop.split(" - ")[0], prop.split(" - ")[1].split())
649 + for prop in props if " - " in prop)
650 + del props
651 + return self._expansion
652 +
653 + @property
654 + def unadded(self):
655 + '''VCS method of getting the unadded files in the repository'''
656 + if self._unadded is not None:
657 + return self._unadded
658 + with repoman_popen("svn status --no-ignore") as f:
659 + svnstatus = f.readlines()
660 + self._unadded = [
661 + "./" + elem.rstrip().split()[1]
662 + for elem in svnstatus
663 + if elem.startswith("?") or elem.startswith("I")]
664 + del svnstatus
665 + return self._unadded