hgext/imerge.py
changeset 5063 86327d13d916
parent 5054 ec70fd08e16c
child 5064 420e1166a876
equal deleted inserted replaced
5054:ec70fd08e16c 5063:86327d13d916
    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)