Show More
@@ -0,0 +1,89 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | "$TESTDIR/hghave" svn svn-bindings || exit 80 | |||
|
4 | ||||
|
5 | fix_path() | |||
|
6 | { | |||
|
7 | tr '\\' / | |||
|
8 | } | |||
|
9 | ||||
|
10 | echo "[extensions]" >> $HGRCPATH | |||
|
11 | echo "convert = " >> $HGRCPATH | |||
|
12 | echo "hgext.graphlog =" >> $HGRCPATH | |||
|
13 | ||||
|
14 | svnadmin create svn-repo | |||
|
15 | ||||
|
16 | svnpath=`pwd | fix_path` | |||
|
17 | # SVN wants all paths to start with a slash. Unfortunately, | |||
|
18 | # Windows ones don't. Handle that. | |||
|
19 | expr $svnpath : "\/" > /dev/null | |||
|
20 | if [ $? -ne 0 ]; then | |||
|
21 | svnpath='/'$svnpath | |||
|
22 | fi | |||
|
23 | ||||
|
24 | echo % initial svn import | |||
|
25 | mkdir projA | |||
|
26 | cd projA | |||
|
27 | mkdir trunk | |||
|
28 | mkdir branches | |||
|
29 | mkdir tags | |||
|
30 | cd .. | |||
|
31 | ||||
|
32 | svnurl=file://$svnpath/svn-repo/projA | |||
|
33 | svn import -m "init projA" projA $svnurl | fix_path | |||
|
34 | ||||
|
35 | echo % update svn repository | |||
|
36 | svn co $svnurl A | fix_path | |||
|
37 | cd A | |||
|
38 | echo hello > trunk/letter.txt | |||
|
39 | echo hey > trunk/letter2.txt | |||
|
40 | echo ho > trunk/letter3.txt | |||
|
41 | svn add trunk/letter.txt trunk/letter2.txt trunk/letter3.txt | |||
|
42 | svn ci -m hello | |||
|
43 | ||||
|
44 | echo % branch to old letters | |||
|
45 | svn copy trunk branches/old | |||
|
46 | svn rm branches/old/letter3.txt | |||
|
47 | svn ci -m "branch trunk, remove letter3" | |||
|
48 | svn up | |||
|
49 | ||||
|
50 | echo % update trunk | |||
|
51 | echo "what can I say ?" >> trunk/letter.txt | |||
|
52 | svn ci -m "change letter" | |||
|
53 | ||||
|
54 | echo % update old branch | |||
|
55 | echo "what's up ?" >> branches/old/letter2.txt | |||
|
56 | svn ci -m "change letter2" | |||
|
57 | ||||
|
58 | echo % create a cross-branch revision | |||
|
59 | svn move -m "move letter2" trunk/letter2.txt \ | |||
|
60 | branches/old/letter3.txt | |||
|
61 | echo "I am fine" >> branches/old/letter3.txt | |||
|
62 | svn ci -m "move and update letter3.txt" | |||
|
63 | ||||
|
64 | echo % update old branch again | |||
|
65 | echo "bye" >> branches/old/letter2.txt | |||
|
66 | svn ci -m "change letter2 again" | |||
|
67 | ||||
|
68 | echo % update trunk again | |||
|
69 | echo "how are you ?" >> trunk/letter.txt | |||
|
70 | svn ci -m "last change to letter" | |||
|
71 | cd .. | |||
|
72 | ||||
|
73 | echo % convert trunk and branches | |||
|
74 | hg convert --datesort $svnurl A-hg | |||
|
75 | ||||
|
76 | echo % branch again from a converted revision | |||
|
77 | cd A | |||
|
78 | svn copy -r 1 $svnurl/trunk branches/old2 | |||
|
79 | svn ci -m "branch trunk@1 into old2" | |||
|
80 | cd .. | |||
|
81 | ||||
|
82 | echo % convert again | |||
|
83 | hg convert --datesort $svnurl A-hg | |||
|
84 | ||||
|
85 | cd A-hg | |||
|
86 | hg glog --template '#rev# #desc|firstline# files: #files#\n' | |||
|
87 | hg branches | sed 's/:.*/:/' | |||
|
88 | hg tags -q | |||
|
89 | cd .. |
@@ -0,0 +1,101 b'' | |||||
|
1 | % initial svn import | |||
|
2 | Adding projA/trunk | |||
|
3 | Adding projA/branches | |||
|
4 | Adding projA/tags | |||
|
5 | ||||
|
6 | Committed revision 1. | |||
|
7 | % update svn repository | |||
|
8 | A A/trunk | |||
|
9 | A A/branches | |||
|
10 | A A/tags | |||
|
11 | Checked out revision 1. | |||
|
12 | A trunk/letter.txt | |||
|
13 | A trunk/letter2.txt | |||
|
14 | A trunk/letter3.txt | |||
|
15 | Adding trunk/letter.txt | |||
|
16 | Adding trunk/letter2.txt | |||
|
17 | Adding trunk/letter3.txt | |||
|
18 | Transmitting file data ... | |||
|
19 | Committed revision 2. | |||
|
20 | % branch to old letters | |||
|
21 | A branches/old | |||
|
22 | D branches/old/letter3.txt | |||
|
23 | Adding branches/old | |||
|
24 | Adding branches/old/letter.txt | |||
|
25 | Adding branches/old/letter2.txt | |||
|
26 | Deleting branches/old/letter3.txt | |||
|
27 | ||||
|
28 | Committed revision 3. | |||
|
29 | At revision 3. | |||
|
30 | % update trunk | |||
|
31 | Sending trunk/letter.txt | |||
|
32 | Transmitting file data . | |||
|
33 | Committed revision 4. | |||
|
34 | % update old branch | |||
|
35 | Sending branches/old/letter2.txt | |||
|
36 | Transmitting file data . | |||
|
37 | Committed revision 5. | |||
|
38 | % create a cross-branch revision | |||
|
39 | A branches/old/letter3.txt | |||
|
40 | D trunk/letter2.txt | |||
|
41 | Adding branches/old/letter3.txt | |||
|
42 | Deleting trunk/letter2.txt | |||
|
43 | Transmitting file data . | |||
|
44 | Committed revision 6. | |||
|
45 | % update old branch again | |||
|
46 | Sending branches/old/letter2.txt | |||
|
47 | Transmitting file data . | |||
|
48 | Committed revision 7. | |||
|
49 | % update trunk again | |||
|
50 | Sending trunk/letter.txt | |||
|
51 | Transmitting file data . | |||
|
52 | Committed revision 8. | |||
|
53 | % convert trunk and branches | |||
|
54 | initializing destination A-hg repository | |||
|
55 | scanning source... | |||
|
56 | sorting... | |||
|
57 | converting... | |||
|
58 | 8 init projA | |||
|
59 | 7 hello | |||
|
60 | 6 branch trunk, remove letter3 | |||
|
61 | 5 change letter | |||
|
62 | 4 change letter2 | |||
|
63 | 3 move and update letter3.txt | |||
|
64 | 2 move and update letter3.txt | |||
|
65 | 1 change letter2 again | |||
|
66 | 0 last change to letter | |||
|
67 | % branch again from a converted revision | |||
|
68 | Checked out revision 1. | |||
|
69 | A branches/old2 | |||
|
70 | Adding branches/old2 | |||
|
71 | ||||
|
72 | Committed revision 9. | |||
|
73 | % convert again | |||
|
74 | scanning source... | |||
|
75 | sorting... | |||
|
76 | converting... | |||
|
77 | 0 branch trunk@1 into old2 | |||
|
78 | o 9 branch trunk@1 into old2 files: | |||
|
79 | | | |||
|
80 | | o 8 last change to letter files: letter.txt | |||
|
81 | | | | |||
|
82 | | | o 7 change letter2 again files: letter2.txt | |||
|
83 | | | | | |||
|
84 | | o | 6 move and update letter3.txt files: letter2.txt | |||
|
85 | | | | | |||
|
86 | | | o 5 move and update letter3.txt files: letter3.txt | |||
|
87 | | | | | |||
|
88 | | | o 4 change letter2 files: letter2.txt | |||
|
89 | | | | | |||
|
90 | | o | 3 change letter files: letter.txt | |||
|
91 | | | | | |||
|
92 | +---o 2 branch trunk, remove letter3 files: letter.txt letter.txt letter2.txt letter2.txt | |||
|
93 | | | | |||
|
94 | | o 1 hello files: letter.txt letter2.txt letter3.txt | |||
|
95 | |/ | |||
|
96 | o 0 init projA files: | |||
|
97 | ||||
|
98 | old2 9: | |||
|
99 | default 8: | |||
|
100 | old 7: | |||
|
101 | tip |
@@ -89,6 +89,9 b' def get_log_child(fp, url, paths, start,' | |||||
89 | receiver) |
|
89 | receiver) | |
90 | except SubversionException, (inst, num): |
|
90 | except SubversionException, (inst, num): | |
91 | pickle.dump(num, fp, protocol) |
|
91 | pickle.dump(num, fp, protocol) | |
|
92 | except IOError: | |||
|
93 | # Caller may interrupt the iteration | |||
|
94 | pickle.dump(None, fp, protocol) | |||
92 | else: |
|
95 | else: | |
93 | pickle.dump(None, fp, protocol) |
|
96 | pickle.dump(None, fp, protocol) | |
94 | fp.close() |
|
97 | fp.close() | |
@@ -102,7 +105,53 b' def debugsvnlog(ui, **opts):' | |||||
102 | args = decodeargs(sys.stdin.read()) |
|
105 | args = decodeargs(sys.stdin.read()) | |
103 | get_log_child(sys.stdout, *args) |
|
106 | get_log_child(sys.stdout, *args) | |
104 |
|
107 | |||
|
108 | class logstream: | |||
|
109 | """Interruptible revision log iterator.""" | |||
|
110 | def __init__(self, stdout): | |||
|
111 | self._stdout = stdout | |||
|
112 | ||||
|
113 | def __iter__(self): | |||
|
114 | while True: | |||
|
115 | entry = pickle.load(self._stdout) | |||
|
116 | try: | |||
|
117 | orig_paths, revnum, author, date, message = entry | |||
|
118 | except: | |||
|
119 | if entry is None: | |||
|
120 | break | |||
|
121 | raise SubversionException("child raised exception", entry) | |||
|
122 | yield entry | |||
|
123 | ||||
|
124 | def close(self): | |||
|
125 | if self._stdout: | |||
|
126 | self._stdout.close() | |||
|
127 | self._stdout = None | |||
|
128 | ||||
|
129 | def get_log(url, paths, start, end, limit=0, discover_changed_paths=True, | |||
|
130 | strict_node_history=False): | |||
|
131 | args = [url, paths, start, end, limit, discover_changed_paths, | |||
|
132 | strict_node_history] | |||
|
133 | arg = encodeargs(args) | |||
|
134 | hgexe = util.hgexecutable() | |||
|
135 | cmd = '%s debugsvnlog' % util.shellquote(hgexe) | |||
|
136 | stdin, stdout = os.popen2(cmd, 'b') | |||
|
137 | stdin.write(arg) | |||
|
138 | stdin.close() | |||
|
139 | return logstream(stdout) | |||
|
140 | ||||
105 | # SVN conversion code stolen from bzr-svn and tailor |
|
141 | # SVN conversion code stolen from bzr-svn and tailor | |
|
142 | # | |||
|
143 | # Subversion looks like a versioned filesystem, branches structures | |||
|
144 | # are defined by conventions and not enforced by the tool. First, | |||
|
145 | # we define the potential branches (modules) as "trunk" and "branches" | |||
|
146 | # children directories. Revisions are then identified by their | |||
|
147 | # module and revision number (and a repository identifier). | |||
|
148 | # | |||
|
149 | # The revision graph is really a tree (or a forest). By default, a | |||
|
150 | # revision parent is the previous revision in the same module. If the | |||
|
151 | # module directory is copied/moved from another module then the | |||
|
152 | # revision is the module root and its parent the source revision in | |||
|
153 | # the parent module. A revision has at most one parent. | |||
|
154 | # | |||
106 | class svn_source(converter_source): |
|
155 | class svn_source(converter_source): | |
107 | def __init__(self, ui, url, rev=None): |
|
156 | def __init__(self, ui, url, rev=None): | |
108 | super(svn_source, self).__init__(ui, url, rev=rev) |
|
157 | super(svn_source, self).__init__(ui, url, rev=rev) | |
@@ -133,7 +182,6 b' class svn_source(converter_source):' | |||||
133 | self.ctx = self.transport.client |
|
182 | self.ctx = self.transport.client | |
134 | self.base = svn.ra.get_repos_root(self.ra) |
|
183 | self.base = svn.ra.get_repos_root(self.ra) | |
135 | self.module = self.url[len(self.base):] |
|
184 | self.module = self.url[len(self.base):] | |
136 | self.modulemap = {} # revision, module |
|
|||
137 | self.commits = {} |
|
185 | self.commits = {} | |
138 | self.paths = {} |
|
186 | self.paths = {} | |
139 | self.uuid = svn.ra.get_uuid(self.ra).decode(self.encoding) |
|
187 | self.uuid = svn.ra.get_uuid(self.ra).decode(self.encoding) | |
@@ -257,45 +305,26 b' class svn_source(converter_source):' | |||||
257 | uuid, module, revnum = self.revsplit(rev) |
|
305 | uuid, module, revnum = self.revsplit(rev) | |
258 | self.module = module |
|
306 | self.module = module | |
259 | self.reparent(module) |
|
307 | self.reparent(module) | |
|
308 | # We assume that: | |||
|
309 | # - requests for revisions after "stop" come from the | |||
|
310 | # revision graph backward traversal. Cache all of them | |||
|
311 | # down to stop, they will be used eventually. | |||
|
312 | # - requests for revisions before "stop" come to get | |||
|
313 | # isolated branches parents. Just fetch what is needed. | |||
260 | stop = self.lastrevs.get(module, 0) |
|
314 | stop = self.lastrevs.get(module, 0) | |
261 | self._fetch_revisions(from_revnum=revnum, to_revnum=stop) |
|
315 | if revnum < stop: | |
|
316 | stop = revnum + 1 | |||
|
317 | self._fetch_revisions(revnum, stop) | |||
262 | commit = self.commits[rev] |
|
318 | commit = self.commits[rev] | |
263 | # caller caches the result, so free it here to release memory |
|
319 | # caller caches the result, so free it here to release memory | |
264 | del self.commits[rev] |
|
320 | del self.commits[rev] | |
265 | return commit |
|
321 | return commit | |
266 |
|
322 | |||
267 | def get_log(self, paths, start, end, limit=0, discover_changed_paths=True, |
|
|||
268 | strict_node_history=False): |
|
|||
269 |
|
||||
270 | def parent(fp): |
|
|||
271 | while True: |
|
|||
272 | entry = pickle.load(fp) |
|
|||
273 | try: |
|
|||
274 | orig_paths, revnum, author, date, message = entry |
|
|||
275 | except: |
|
|||
276 | if entry is None: |
|
|||
277 | break |
|
|||
278 | raise SubversionException("child raised exception", entry) |
|
|||
279 | yield entry |
|
|||
280 |
|
||||
281 | args = [self.url, paths, start, end, limit, discover_changed_paths, |
|
|||
282 | strict_node_history] |
|
|||
283 | arg = encodeargs(args) |
|
|||
284 | hgexe = util.hgexecutable() |
|
|||
285 | cmd = '%s debugsvnlog' % util.shellquote(hgexe) |
|
|||
286 | stdin, stdout = os.popen2(cmd, 'b') |
|
|||
287 |
|
||||
288 | stdin.write(arg) |
|
|||
289 | stdin.close() |
|
|||
290 |
|
||||
291 | for p in parent(stdout): |
|
|||
292 | yield p |
|
|||
293 |
|
||||
294 | def gettags(self): |
|
323 | def gettags(self): | |
295 | tags = {} |
|
324 | tags = {} | |
296 | start = self.revnum(self.head) |
|
325 | start = self.revnum(self.head) | |
297 | try: |
|
326 | try: | |
298 |
for entry in self. |
|
327 | for entry in get_log(self.url, [self.tags], 0, start): | |
299 | orig_paths, revnum, author, date, message = entry |
|
328 | orig_paths, revnum, author, date, message = entry | |
300 | for path in orig_paths: |
|
329 | for path in orig_paths: | |
301 | if not path.startswith(self.tags+'/'): |
|
330 | if not path.startswith(self.tags+'/'): | |
@@ -400,13 +429,11 b' class svn_source(converter_source):' | |||||
400 | entries = [] |
|
429 | entries = [] | |
401 | copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions. |
|
430 | copyfrom = {} # Map of entrypath, revision for finding source of deleted revisions. | |
402 | copies = {} |
|
431 | copies = {} | |
403 | revnum = self.revnum(rev) |
|
|||
404 |
|
432 | |||
405 | if revnum in self.modulemap: |
|
433 | new_module, revnum = self.revsplit(rev)[1:] | |
406 |
|
|
434 | if new_module != self.module: | |
407 |
|
|
435 | self.module = new_module | |
408 | self.module = new_module |
|
436 | self.reparent(self.module) | |
409 | self.reparent(self.module) |
|
|||
410 |
|
437 | |||
411 | for path, ent in paths: |
|
438 | for path, ent in paths: | |
412 | entrypath = get_entry_from_path(path, module=self.module) |
|
439 | entrypath = get_entry_from_path(path, module=self.module) | |
@@ -432,12 +459,9 b' class svn_source(converter_source):' | |||||
432 |
|
459 | |||
433 | # if a branch is created but entries are removed in the same |
|
460 | # if a branch is created but entries are removed in the same | |
434 | # changeset, get the right fromrev |
|
461 | # changeset, get the right fromrev | |
435 | if parents: |
|
462 | # parents cannot be empty here, you cannot remove things from | |
436 | uuid, old_module, fromrev = self.revsplit(parents[0]) |
|
463 | # a root revision. | |
437 | else: |
|
464 | uuid, old_module, fromrev = self.revsplit(parents[0]) | |
438 | fromrev = revnum - 1 |
|
|||
439 | # might always need to be revnum - 1 in these 3 lines? |
|
|||
440 | old_module = self.modulemap.get(fromrev, self.module) |
|
|||
441 |
|
465 | |||
442 | basepath = old_module + "/" + get_entry_from_path(path, module=self.module) |
|
466 | basepath = old_module + "/" + get_entry_from_path(path, module=self.module) | |
443 | entrypath = old_module + "/" + get_entry_from_path(path, module=self.module) |
|
467 | entrypath = old_module + "/" + get_entry_from_path(path, module=self.module) | |
@@ -508,6 +532,9 b' class svn_source(converter_source):' | |||||
508 |
|
532 | |||
509 | # If the directory just had a prop change, |
|
533 | # If the directory just had a prop change, | |
510 | # then we shouldn't need to look for its children. |
|
534 | # then we shouldn't need to look for its children. | |
|
535 | if ent.action == 'M': | |||
|
536 | continue | |||
|
537 | ||||
511 | # Also this could create duplicate entries. Not sure |
|
538 | # Also this could create duplicate entries. Not sure | |
512 | # whether this will matter. Maybe should make entries a set. |
|
539 | # whether this will matter. Maybe should make entries a set. | |
513 | # print "Changed directory", revnum, path, ent.action, ent.copyfrom_path, ent.copyfrom_rev |
|
540 | # print "Changed directory", revnum, path, ent.action, ent.copyfrom_path, ent.copyfrom_rev | |
@@ -568,23 +595,23 b' class svn_source(converter_source):' | |||||
568 |
|
595 | |||
569 | return (entries, copies) |
|
596 | return (entries, copies) | |
570 |
|
597 | |||
571 |
def _fetch_revisions(self, from_revnum |
|
598 | def _fetch_revisions(self, from_revnum, to_revnum): | |
|
599 | if from_revnum < to_revnum: | |||
|
600 | from_revnum, to_revnum = to_revnum, from_revnum | |||
|
601 | ||||
572 | self.child_cset = None |
|
602 | self.child_cset = None | |
573 | def parselogentry(orig_paths, revnum, author, date, message): |
|
603 | def parselogentry(orig_paths, revnum, author, date, message): | |
|
604 | """Return the parsed commit object or None, and True if | |||
|
605 | the revision is a branch root. | |||
|
606 | """ | |||
574 | self.ui.debug("parsing revision %d (%d changes)\n" % |
|
607 | self.ui.debug("parsing revision %d (%d changes)\n" % | |
575 | (revnum, len(orig_paths))) |
|
608 | (revnum, len(orig_paths))) | |
576 |
|
609 | |||
577 | if revnum in self.modulemap: |
|
|||
578 | new_module = self.modulemap[revnum] |
|
|||
579 | if new_module != self.module: |
|
|||
580 | self.module = new_module |
|
|||
581 | self.reparent(self.module) |
|
|||
582 |
|
||||
583 | rev = self.revid(revnum) |
|
610 | rev = self.revid(revnum) | |
584 | # branch log might return entries for a parent we already have |
|
611 | # branch log might return entries for a parent we already have | |
585 | if (rev in self.commits or |
|
612 | ||
586 | (revnum < self.lastrevs.get(self.module, 0))): |
|
613 | if (rev in self.commits or revnum < to_revnum): | |
587 | return |
|
614 | return None, False | |
588 |
|
615 | |||
589 | parents = [] |
|
616 | parents = [] | |
590 | # check whether this revision is the start of a branch |
|
617 | # check whether this revision is the start of a branch | |
@@ -593,15 +620,12 b' class svn_source(converter_source):' | |||||
593 | if ent.copyfrom_path: |
|
620 | if ent.copyfrom_path: | |
594 | # ent.copyfrom_rev may not be the actual last revision |
|
621 | # ent.copyfrom_rev may not be the actual last revision | |
595 | prev = self.latest(ent.copyfrom_path, ent.copyfrom_rev) |
|
622 | prev = self.latest(ent.copyfrom_path, ent.copyfrom_rev) | |
596 | self.modulemap[prev] = ent.copyfrom_path |
|
|||
597 | parents = [self.revid(prev, ent.copyfrom_path)] |
|
623 | parents = [self.revid(prev, ent.copyfrom_path)] | |
598 | self.ui.note('found parent of branch %s at %d: %s\n' % \ |
|
624 | self.ui.note('found parent of branch %s at %d: %s\n' % \ | |
599 | (self.module, prev, ent.copyfrom_path)) |
|
625 | (self.module, prev, ent.copyfrom_path)) | |
600 | else: |
|
626 | else: | |
601 | self.ui.debug("No copyfrom path, don't know what to do.\n") |
|
627 | self.ui.debug("No copyfrom path, don't know what to do.\n") | |
602 |
|
628 | |||
603 | self.modulemap[revnum] = self.module # track backwards in time |
|
|||
604 |
|
||||
605 | orig_paths = orig_paths.items() |
|
629 | orig_paths = orig_paths.items() | |
606 | orig_paths.sort() |
|
630 | orig_paths.sort() | |
607 | paths = [] |
|
631 | paths = [] | |
@@ -612,8 +636,6 b' class svn_source(converter_source):' | |||||
612 | continue |
|
636 | continue | |
613 | paths.append((path, ent)) |
|
637 | paths.append((path, ent)) | |
614 |
|
638 | |||
615 | self.paths[rev] = (paths, parents) |
|
|||
616 |
|
||||
617 | # Example SVN datetime. Includes microseconds. |
|
639 | # Example SVN datetime. Includes microseconds. | |
618 | # ISO-8601 conformant |
|
640 | # ISO-8601 conformant | |
619 | # '2007-01-04T17:35:00.902377Z' |
|
641 | # '2007-01-04T17:35:00.902377Z' | |
@@ -636,23 +658,50 b' class svn_source(converter_source):' | |||||
636 | rev=rev.encode('utf-8')) |
|
658 | rev=rev.encode('utf-8')) | |
637 |
|
659 | |||
638 | self.commits[rev] = cset |
|
660 | self.commits[rev] = cset | |
|
661 | # The parents list is *shared* among self.paths and the | |||
|
662 | # commit object. Both will be updated below. | |||
|
663 | self.paths[rev] = (paths, cset.parents) | |||
639 | if self.child_cset and not self.child_cset.parents: |
|
664 | if self.child_cset and not self.child_cset.parents: | |
640 | self.child_cset.parents = [rev] |
|
665 | self.child_cset.parents[:] = [rev] | |
641 | self.child_cset = cset |
|
666 | self.child_cset = cset | |
|
667 | return cset, len(parents) > 0 | |||
642 |
|
668 | |||
643 | self.ui.note('fetching revision log for "%s" from %d to %d\n' % |
|
669 | self.ui.note('fetching revision log for "%s" from %d to %d\n' % | |
644 | (self.module, from_revnum, to_revnum)) |
|
670 | (self.module, from_revnum, to_revnum)) | |
645 |
|
671 | |||
646 | try: |
|
672 | try: | |
647 | for entry in self.get_log([self.module], from_revnum, to_revnum): |
|
673 | firstcset = None | |
648 | orig_paths, revnum, author, date, message = entry |
|
674 | stream = get_log(self.url, [self.module], from_revnum, to_revnum) | |
649 | if self.is_blacklisted(revnum): |
|
675 | try: | |
650 | self.ui.note('skipping blacklisted revision %d\n' % revnum) |
|
676 | for entry in stream: | |
651 | continue |
|
677 | paths, revnum, author, date, message = entry | |
652 | if orig_paths is None: |
|
678 | if self.is_blacklisted(revnum): | |
653 |
self.ui. |
|
679 | self.ui.note('skipping blacklisted revision %d\n' | |
654 | continue |
|
680 | % revnum) | |
655 | parselogentry(orig_paths, revnum, author, date, message) |
|
681 | continue | |
|
682 | if paths is None: | |||
|
683 | self.ui.debug('revision %d has no entries\n' % revnum) | |||
|
684 | continue | |||
|
685 | cset, branched = parselogentry(paths, revnum, author, | |||
|
686 | date, message) | |||
|
687 | if cset: | |||
|
688 | firstcset = cset | |||
|
689 | if branched: | |||
|
690 | break | |||
|
691 | finally: | |||
|
692 | stream.close() | |||
|
693 | ||||
|
694 | if firstcset and not firstcset.parents: | |||
|
695 | # The first revision of the sequence (the last fetched one) | |||
|
696 | # has invalid parents if not a branch root. Find the parent | |||
|
697 | # revision now, if any. | |||
|
698 | try: | |||
|
699 | firstrevnum = self.revnum(firstcset.rev) | |||
|
700 | if firstrevnum > 1: | |||
|
701 | latest = self.latest(self.module, firstrevnum - 1) | |||
|
702 | firstcset.parents.append(self.revid(latest)) | |||
|
703 | except util.Abort: | |||
|
704 | pass | |||
656 | except SubversionException, (inst, num): |
|
705 | except SubversionException, (inst, num): | |
657 | if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION: |
|
706 | if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION: | |
658 | raise NoSuchRevision(branch=self, |
|
707 | raise NoSuchRevision(branch=self, | |
@@ -664,9 +713,9 b' class svn_source(converter_source):' | |||||
664 | # TODO: ra.get_file transmits the whole file instead of diffs. |
|
713 | # TODO: ra.get_file transmits the whole file instead of diffs. | |
665 | mode = '' |
|
714 | mode = '' | |
666 | try: |
|
715 | try: | |
667 |
revnum = self.rev |
|
716 | new_module, revnum = self.revsplit(rev)[1:] | |
668 |
if self.module != |
|
717 | if self.module != new_module: | |
669 |
self.module = |
|
718 | self.module = new_module | |
670 | self.reparent(self.module) |
|
719 | self.reparent(self.module) | |
671 | info = svn.ra.get_file(self.ra, file, revnum, io) |
|
720 | info = svn.ra.get_file(self.ra, file, revnum, io) | |
672 | if isinstance(info, list): |
|
721 | if isinstance(info, list): |
General Comments 0
You need to be logged in to leave comments.
Login now