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