21 |
21 |
22 st = os.path.join(self.im.path, 'status') |
22 st = os.path.join(self.im.path, 'status') |
23 tf.add(st, os.path.join('.hg', 'imerge', 'status')) |
23 tf.add(st, os.path.join('.hg', 'imerge', 'status')) |
24 |
24 |
25 for f in self.im.resolved: |
25 for f in self.im.resolved: |
26 abssrc = self.im.repo.wjoin(f) |
26 (fd, fo) = self.im.conflicts[f] |
27 tf.add(abssrc, f) |
27 abssrc = self.im.repo.wjoin(fd) |
|
28 tf.add(abssrc, fd) |
28 |
29 |
29 tf.close() |
30 tf.close() |
30 |
31 |
31 def load(self, source): |
32 def load(self, source): |
32 wlock = self.im.repo.wlock() |
33 wlock = self.im.repo.wlock() |
37 statusfile = os.path.join('.hg', 'imerge', 'status') |
38 statusfile = os.path.join('.hg', 'imerge', 'status') |
38 if statusfile not in contents: |
39 if statusfile not in contents: |
39 raise InvalidStateFileException('no status file') |
40 raise InvalidStateFileException('no status file') |
40 |
41 |
41 tf.extract(statusfile, self.im.repo.root) |
42 tf.extract(statusfile, self.im.repo.root) |
42 self.im.load() |
43 p1, p2 = self.im.load() |
43 p1 = self.im.parents[0].node() |
44 if self.im.repo.dirstate.parents()[0] != p1.node(): |
44 p2 = self.im.parents[1].node() |
45 hg.clean(self.im.repo, p1.node()) |
45 if self.im.repo.dirstate.parents()[0] != p1: |
46 self.im.start(p2.node()) |
46 hg.clean(self.im.repo, self.im.parents[0].node()) |
|
47 self.im.start(p2) |
|
48 tf.extractall(self.im.repo.root) |
47 tf.extractall(self.im.repo.root) |
49 self.im.load() |
48 self.im.load() |
50 |
49 |
51 class Imerge(object): |
50 class Imerge(object): |
52 def __init__(self, ui, repo): |
51 def __init__(self, ui, repo): |
54 self.repo = repo |
53 self.repo = repo |
55 |
54 |
56 self.path = repo.join('imerge') |
55 self.path = repo.join('imerge') |
57 self.opener = util.opener(self.path) |
56 self.opener = util.opener(self.path) |
58 |
57 |
59 self.parents = [self.repo.changectx(n) |
58 self.wctx = self.repo.workingctx() |
60 for n in self.repo.dirstate.parents()] |
|
61 self.conflicts = {} |
59 self.conflicts = {} |
62 self.resolved = [] |
60 self.resolved = [] |
63 |
61 |
64 def merging(self): |
62 def merging(self): |
65 return self.parents[1].node() != nullid |
63 return len(self.wctx.parents()) > 1 |
66 |
64 |
67 def load(self): |
65 def load(self): |
68 # status format. \0-delimited file, fields are |
66 # status format. \0-delimited file, fields are |
69 # p1, p2, conflict count, conflict filenames, resolved filenames |
67 # p1, p2, conflict count, conflict filenames, resolved filenames |
70 # conflict filenames are tuples of localname, remoteorig, remotenew |
68 # conflict filenames are tuples of localname, remoteorig, remotenew |
74 status = statusfile.read().split('\0') |
72 status = statusfile.read().split('\0') |
75 if len(status) < 3: |
73 if len(status) < 3: |
76 raise util.Abort('invalid imerge status file') |
74 raise util.Abort('invalid imerge status file') |
77 |
75 |
78 try: |
76 try: |
79 self.parents = [self.repo.changectx(n) for n in status[:2]] |
77 parents = [self.repo.changectx(n) for n in status[:2]] |
80 except LookupError: |
78 except LookupError: |
81 raise util.Abort('merge parent %s not in repository' % short(p)) |
79 raise util.Abort('merge parent %s not in repository' % short(p)) |
82 |
80 |
83 status = status[2:] |
81 status = status[2:] |
84 conflicts = int(status.pop(0)) * 3 |
82 conflicts = int(status.pop(0)) * 3 |
85 self.resolved = status[conflicts:] |
83 self.resolved = status[conflicts:] |
86 for i in xrange(0, conflicts, 3): |
84 for i in xrange(0, conflicts, 3): |
87 self.conflicts[status[i]] = (status[i+1], status[i+2]) |
85 self.conflicts[status[i]] = (status[i+1], status[i+2]) |
88 |
86 |
|
87 return parents |
|
88 |
89 def save(self): |
89 def save(self): |
90 lock = self.repo.lock() |
90 lock = self.repo.lock() |
91 |
91 |
92 if not os.path.isdir(self.path): |
92 if not os.path.isdir(self.path): |
93 os.mkdir(self.path) |
93 os.mkdir(self.path) |
94 fd = self.opener('status', 'wb') |
94 fd = self.opener('status', 'wb') |
95 |
95 |
96 out = [hex(n.node()) for n in self.parents] |
96 out = [hex(n.node()) for n in self.wctx.parents()] |
97 out.append(str(len(self.conflicts))) |
97 out.append(str(len(self.conflicts))) |
98 for f in sorted(self.conflicts): |
98 for f in sorted(self.conflicts): |
99 out.append(f) |
99 out.append(f) |
100 out.extend(self.conflicts[f]) |
100 out.extend(self.conflicts[f]) |
101 out.extend(self.resolved) |
101 out.extend(self.resolved) |
107 |
107 |
108 def filemerge(self, fn): |
108 def filemerge(self, fn): |
109 wlock = self.repo.wlock() |
109 wlock = self.repo.wlock() |
110 |
110 |
111 (fd, fo) = self.conflicts[fn] |
111 (fd, fo) = self.conflicts[fn] |
112 return merge.filemerge(self.repo, fn, fd, fo, self.parents[0], |
112 p2 = self.wctx.parents()[1] |
113 self.parents[1]) |
113 return merge.filemerge(self.repo, fn, fd, fo, self.wctx, p2) |
114 |
114 |
115 def start(self, rev=None): |
115 def start(self, rev=None): |
116 _filemerge = merge.filemerge |
116 _filemerge = merge.filemerge |
117 def filemerge(repo, fw, fd, fo, wctx, mctx): |
117 def filemerge(repo, fw, fd, fo, wctx, mctx): |
118 self.conflicts[fw] = (fd, fo) |
118 self.conflicts[fw] = (fd, fo) |
119 |
119 |
120 merge.filemerge = filemerge |
120 merge.filemerge = filemerge |
121 commands.merge(self.ui, self.repo, rev=rev) |
121 commands.merge(self.ui, self.repo, rev=rev) |
122 merge.filemerge = _filemerge |
122 merge.filemerge = _filemerge |
123 |
123 |
124 self.parents = [self.repo.changectx(n) |
124 self.wctx = self.repo.workingctx() |
125 for n in self.repo.dirstate.parents()] |
|
126 self.save() |
125 self.save() |
127 |
126 |
128 def resume(self): |
127 def resume(self): |
129 self.load() |
128 self.load() |
130 |
129 |
131 dp = self.repo.dirstate.parents() |
130 dp = self.repo.dirstate.parents() |
132 if self.parents[0].node() != dp[0] or self.parents[1].node() != dp[1]: |
131 p1, p2 = self.wctx.parents() |
|
132 if p1.node() != dp[0] or p2.node() != dp[1]: |
133 raise util.Abort('imerge state does not match working directory') |
133 raise util.Abort('imerge state does not match working directory') |
134 |
134 |
135 def status(self): |
135 def status(self): |
|
136 p1, p2 = self.wctx.parents() |
136 self.ui.write('merging %s and %s\n' % \ |
137 self.ui.write('merging %s and %s\n' % \ |
137 (short(self.parents[0].node()), |
138 (short(p1.node()), short(p2.node()))) |
138 short(self.parents[1].node()))) |
|
139 |
139 |
140 if self.resolved: |
140 if self.resolved: |
141 self.ui.write('resolved:\n') |
141 self.ui.write('resolved:\n') |
142 for fn in self.resolved: |
142 for fn in self.resolved: |
143 self.ui.write(' %s\n' % fn) |
143 self.ui.write(' %s\n' % fn) |