Mercurial > hg
comparison hgext/convert/cvs.py @ 6690:127e8c3466d1
convert: cvs.py - Allow user to use built-in CVS changeset code.
tests: add two testcases for CVS conversion with builtin CVS
including a testcase for issue 1148.
author | Frank Kingswood <frank@kingswood-consulting.co.uk> |
---|---|
date | Sun, 15 Jun 2008 16:05:46 +0100 |
parents | 308988071b90 |
children | f67d1468ac50 |
comparison
equal
deleted
inserted
replaced
6689:d2ac53fe216e | 6690:127e8c3466d1 |
---|---|
1 # CVS conversion code inspired by hg-cvs-import and git-cvsimport | 1 # CVS conversion code inspired by hg-cvs-import and git-cvsimport |
2 | 2 |
3 import os, locale, re, socket | 3 import os, locale, re, socket |
4 from cStringIO import StringIO | 4 from cStringIO import StringIO |
5 from mercurial import util | 5 from mercurial import util |
6 from mercurial.i18n import _ | |
6 | 7 |
7 from common import NoRepo, commit, converter_source, checktool | 8 from common import NoRepo, commit, converter_source, checktool |
9 import cvsps | |
8 | 10 |
9 class convert_cvs(converter_source): | 11 class convert_cvs(converter_source): |
10 def __init__(self, ui, path, rev=None): | 12 def __init__(self, ui, path, rev=None): |
11 super(convert_cvs, self).__init__(ui, path, rev=rev) | 13 super(convert_cvs, self).__init__(ui, path, rev=rev) |
12 | 14 |
13 cvs = os.path.join(path, "CVS") | 15 cvs = os.path.join(path, "CVS") |
14 if not os.path.exists(cvs): | 16 if not os.path.exists(cvs): |
15 raise NoRepo("%s does not look like a CVS checkout" % path) | 17 raise NoRepo("%s does not look like a CVS checkout" % path) |
16 | 18 |
19 checktool('cvs') | |
17 self.cmd = ui.config('convert', 'cvsps', 'cvsps -A -u --cvs-direct -q') | 20 self.cmd = ui.config('convert', 'cvsps', 'cvsps -A -u --cvs-direct -q') |
18 cvspsexe = self.cmd.split(None, 1)[0] | 21 cvspsexe = self.cmd.split(None, 1)[0] |
19 for tool in (cvspsexe, 'cvs'): | 22 self.builtin = cvspsexe == 'builtin' |
20 checktool(tool) | 23 |
24 if not self.builtin: | |
25 checktool(cvspsexe) | |
21 | 26 |
22 self.changeset = {} | 27 self.changeset = {} |
23 self.files = {} | 28 self.files = {} |
24 self.tags = {} | 29 self.tags = {} |
25 self.lastbranch = {} | 30 self.lastbranch = {} |
26 self.parent = {} | 31 self.parent = {} |
27 self.socket = None | 32 self.socket = None |
28 self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1] | 33 self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1] |
29 self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1] | 34 self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1] |
30 self.encoding = locale.getpreferredencoding() | 35 self.encoding = locale.getpreferredencoding() |
31 self._parse() | 36 |
37 self._parse(ui) | |
32 self._connect() | 38 self._connect() |
33 | 39 |
34 def _parse(self): | 40 def _parse(self, ui): |
35 if self.changeset: | 41 if self.changeset: |
36 return | 42 return |
37 | 43 |
38 maxrev = 0 | 44 maxrev = 0 |
39 cmd = self.cmd | 45 cmd = self.cmd |
54 try: | 60 try: |
55 os.chdir(self.path) | 61 os.chdir(self.path) |
56 id = None | 62 id = None |
57 state = 0 | 63 state = 0 |
58 filerevids = {} | 64 filerevids = {} |
59 for l in util.popen(cmd): | 65 |
60 if state == 0: # header | 66 if self.builtin: |
61 if l.startswith("PatchSet"): | 67 # builtin cvsps code |
62 id = l[9:-2] | 68 ui.status(_('using builtin cvsps\n')) |
63 if maxrev and int(id) > maxrev: | 69 |
64 # ignore everything | 70 db = cvsps.createlog(ui, cache='update') |
65 state = 3 | 71 db = cvsps.createchangeset(ui, db, |
66 elif l.startswith("Date"): | 72 fuzz=int(ui.config('convert', 'cvsps.fuzz', 60)), |
67 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"]) | 73 mergeto=ui.config('convert', 'cvsps.mergeto', None), |
68 date = util.datestr(date) | 74 mergefrom=ui.config('convert', 'cvsps.mergefrom', None)) |
69 elif l.startswith("Branch"): | 75 |
70 branch = l[8:-1] | 76 for cs in db: |
71 self.parent[id] = self.lastbranch.get(branch, 'bad') | 77 if maxrev and cs.id>maxrev: |
72 self.lastbranch[branch] = id | 78 break |
73 elif l.startswith("Ancestor branch"): | 79 id = str(cs.id) |
74 ancestor = l[17:-1] | 80 cs.author = self.recode(cs.author) |
75 # figure out the parent later | 81 self.lastbranch[cs.branch] = id |
76 self.parent[id] = self.lastbranch[ancestor] | 82 cs.comment = self.recode(cs.comment) |
77 elif l.startswith("Author"): | 83 date = util.datestr(cs.date) |
78 author = self.recode(l[8:-1]) | 84 self.tags.update(dict.fromkeys(cs.tags, id)) |
79 elif l.startswith("Tag:") or l.startswith("Tags:"): | 85 |
80 t = l[l.index(':')+1:] | 86 files = {} |
81 t = [ut.strip() for ut in t.split(',')] | 87 for f in cs.entries: |
82 if (len(t) > 1) or (t[0] and (t[0] != "(none)")): | 88 files[f.file] = "%s%s" % ('.'.join([str(x) for x in f.revision]), |
83 self.tags.update(dict.fromkeys(t, id)) | 89 ['', '(DEAD)'][f.dead]) |
84 elif l.startswith("Log:"): | 90 |
85 # switch to gathering log | 91 # add current commit to set |
86 state = 1 | 92 c = commit(author=cs.author, date=date, |
87 log = "" | 93 parents=[str(p.id) for p in cs.parents], |
88 elif state == 1: # log | 94 desc=cs.comment, branch=cs.branch or '') |
89 if l == "Members: \n": | 95 self.changeset[id] = c |
90 # switch to gathering members | 96 self.files[id] = files |
91 files = {} | 97 else: |
92 oldrevs = [] | 98 # external cvsps |
93 log = self.recode(log[:-1]) | 99 for l in util.popen(cmd): |
94 state = 2 | 100 if state == 0: # header |
95 else: | 101 if l.startswith("PatchSet"): |
96 # gather log | 102 id = l[9:-2] |
97 log += l | 103 if maxrev and int(id) > maxrev: |
98 elif state == 2: # members | 104 # ignore everything |
99 if l == "\n": # start of next entry | 105 state = 3 |
100 state = 0 | 106 elif l.startswith("Date"): |
101 p = [self.parent[id]] | 107 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"]) |
102 if id == "1": | 108 date = util.datestr(date) |
103 p = [] | 109 elif l.startswith("Branch"): |
104 if branch == "HEAD": | 110 branch = l[8:-1] |
105 branch = "" | 111 self.parent[id] = self.lastbranch.get(branch, 'bad') |
106 if branch: | 112 self.lastbranch[branch] = id |
107 latest = None | 113 elif l.startswith("Ancestor branch"): |
108 # the last changeset that contains a base | 114 ancestor = l[17:-1] |
109 # file is our parent | 115 # figure out the parent later |
110 for r in oldrevs: | 116 self.parent[id] = self.lastbranch[ancestor] |
111 latest = max(filerevids.get(r, None), latest) | 117 elif l.startswith("Author"): |
112 if latest: | 118 author = self.recode(l[8:-1]) |
113 p = [latest] | 119 elif l.startswith("Tag:") or l.startswith("Tags:"): |
114 | 120 t = l[l.index(':')+1:] |
115 # add current commit to set | 121 t = [ut.strip() for ut in t.split(',')] |
116 c = commit(author=author, date=date, parents=p, | 122 if (len(t) > 1) or (t[0] and (t[0] != "(none)")): |
117 desc=log, branch=branch) | 123 self.tags.update(dict.fromkeys(t, id)) |
118 self.changeset[id] = c | 124 elif l.startswith("Log:"): |
119 self.files[id] = files | 125 # switch to gathering log |
120 else: | 126 state = 1 |
121 colon = l.rfind(':') | 127 log = "" |
122 file = l[1:colon] | 128 elif state == 1: # log |
123 rev = l[colon+1:-2] | 129 if l == "Members: \n": |
124 oldrev, rev = rev.split("->") | 130 # switch to gathering members |
125 files[file] = rev | 131 files = {} |
126 | 132 oldrevs = [] |
127 # save some information for identifying branch points | 133 log = self.recode(log[:-1]) |
128 oldrevs.append("%s:%s" % (oldrev, file)) | 134 state = 2 |
129 filerevids["%s:%s" % (rev, file)] = id | 135 else: |
130 elif state == 3: | 136 # gather log |
131 # swallow all input | 137 log += l |
132 continue | 138 elif state == 2: # members |
139 if l == "\n": # start of next entry | |
140 state = 0 | |
141 p = [self.parent[id]] | |
142 if id == "1": | |
143 p = [] | |
144 if branch == "HEAD": | |
145 branch = "" | |
146 if branch: | |
147 latest = None | |
148 # the last changeset that contains a base | |
149 # file is our parent | |
150 for r in oldrevs: | |
151 latest = max(filerevids.get(r, None), latest) | |
152 if latest: | |
153 p = [latest] | |
154 | |
155 # add current commit to set | |
156 c = commit(author=author, date=date, parents=p, | |
157 desc=log, branch=branch) | |
158 self.changeset[id] = c | |
159 self.files[id] = files | |
160 else: | |
161 colon = l.rfind(':') | |
162 file = l[1:colon] | |
163 rev = l[colon+1:-2] | |
164 oldrev, rev = rev.split("->") | |
165 files[file] = rev | |
166 | |
167 # save some information for identifying branch points | |
168 oldrevs.append("%s:%s" % (oldrev, file)) | |
169 filerevids["%s:%s" % (rev, file)] = id | |
170 elif state == 3: | |
171 # swallow all input | |
172 continue | |
133 | 173 |
134 self.heads = self.lastbranch.values() | 174 self.heads = self.lastbranch.values() |
135 finally: | 175 finally: |
136 os.chdir(d) | 176 os.chdir(d) |
137 | 177 |