hgext/record.py
author Kirill Smelkov <kirr@mns.spb.ru>
Thu, 10 Jan 2008 12:07:18 +0300
changeset 5830 c32d41affb68
parent 5827 0c29977bd7db
child 5932 b014ff3fdaeb
permissions -rw-r--r--
hg qrecord -- like record, but for mq I'm a former Darcs user, and I've discovered that it is very convenient to actually perform development using MQ first, and only when the patches are 'ready' move them to project's history in stone. Usually I work on some topic, temporarily forgetting about any version control, and just do coding, experimenting, debugging, etc. After some time, I approach a moment, where my work should actually go to patches/commits, and here is the problem:: As it is now, there is no way to put part of the changes into one patch, and another part of the changes into second patch. This works, but only when changes are touching separate files, and for semantically different changes touching the same file(s) there is now pretty way to put them into separate patches. For some time, I've tolerated the pain to run vim patches/... and move hunks between files by hand, but I think this affects my productivity badly. So, here is the first step towards untiing the problem: Let's use 'hg qrecord' for mq, like we use 'hg record' for usual commits!
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     1
# record.py
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     2
#
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     3
# Copyright 2007 Bryan O'Sullivan <bos@serpentine.com>
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     4
#
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     6
# the GNU General Public License, incorporated herein by reference.
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     7
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
     8
'''interactive change selection during commit or qrefresh'''
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
     9
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    10
from mercurial.i18n import _
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
    11
from mercurial import cmdutil, commands, cmdutil, extensions, hg, mdiff, patch, revlog
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    12
from mercurial import util
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    13
import copy, cStringIO, errno, operator, os, re, shutil, tempfile
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    14
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    15
lines_re = re.compile(r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@\s*(.*)')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    16
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    17
def scanpatch(fp):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    18
    """like patch.iterhunks, but yield different events
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    19
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    20
    - ('file',    [header_lines + fromfile + tofile])
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    21
    - ('context', [context_lines])
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    22
    - ('hunk',    [hunk_lines])
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    23
    - ('range',   (-start,len, +start,len, diffp))
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    24
    """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    25
    lr = patch.linereader(fp)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    26
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    27
    def scanwhile(first, p):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    28
        """scan lr while predicate holds"""
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    29
        lines = [first]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    30
        while True:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    31
            line = lr.readline()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    32
            if not line:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    33
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    34
            if p(line):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    35
                lines.append(line)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    36
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    37
                lr.push(line)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    38
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    39
        return lines
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    40
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    41
    while True:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    42
        line = lr.readline()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    43
        if not line:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    44
            break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    45
        if line.startswith('diff --git a/'):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    46
            def notheader(line):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    47
                s = line.split(None, 1)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    48
                return not s or s[0] not in ('---', 'diff')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    49
            header = scanwhile(line, notheader)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    50
            fromfile = lr.readline()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    51
            if fromfile.startswith('---'):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    52
                tofile = lr.readline()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    53
                header += [fromfile, tofile]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    54
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    55
                lr.push(fromfile)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    56
            yield 'file', header
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    57
        elif line[0] == ' ':
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    58
            yield 'context', scanwhile(line, lambda l: l[0] in ' \\')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    59
        elif line[0] in '-+':
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    60
            yield 'hunk', scanwhile(line, lambda l: l[0] in '-+\\')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    61
        else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    62
            m = lines_re.match(line)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    63
            if m:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    64
                yield 'range', m.groups()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    65
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    66
                raise patch.PatchError('unknown patch content: %r' % line)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    67
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    68
class header(object):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    69
    """patch header
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    70
    
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    71
    XXX shoudn't we move this to mercurial/patch.py ? 
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
    72
    """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    73
    diff_re = re.compile('diff --git a/(.*) b/(.*)$')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    74
    allhunks_re = re.compile('(?:index|new file|deleted file) ')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    75
    pretty_re = re.compile('(?:new file|deleted file) ')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    76
    special_re = re.compile('(?:index|new|deleted|copy|rename) ')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    77
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    78
    def __init__(self, header):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    79
        self.header = header
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    80
        self.hunks = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    81
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    82
    def binary(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    83
        for h in self.header:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    84
            if h.startswith('index '):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    85
                return True
5143
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5129
diff changeset
    86
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    87
    def pretty(self, fp):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    88
        for h in self.header:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    89
            if h.startswith('index '):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    90
                fp.write(_('this modifies a binary file (all or nothing)\n'))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    91
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    92
            if self.pretty_re.match(h):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    93
                fp.write(h)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    94
                if self.binary():
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    95
                    fp.write(_('this is a binary file\n'))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    96
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    97
            if h.startswith('---'):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    98
                fp.write(_('%d hunks, %d lines changed\n') %
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
    99
                         (len(self.hunks),
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   100
                          sum([h.added + h.removed for h in self.hunks])))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   101
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   102
            fp.write(h)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   103
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   104
    def write(self, fp):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   105
        fp.write(''.join(self.header))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   106
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   107
    def allhunks(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   108
        for h in self.header:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   109
            if self.allhunks_re.match(h):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   110
                return True
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   111
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   112
    def files(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   113
        fromfile, tofile = self.diff_re.match(self.header[0]).groups()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   114
        if fromfile == tofile:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   115
            return [fromfile]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   116
        return [fromfile, tofile]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   117
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   118
    def filename(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   119
        return self.files()[-1]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   120
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   121
    def __repr__(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   122
        return '<header %s>' % (' '.join(map(repr, self.files())))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   123
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   124
    def special(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   125
        for h in self.header:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   126
            if self.special_re.match(h):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   127
                return True
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   128
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   129
def countchanges(hunk):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   130
    """hunk -> (n+,n-)"""
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   131
    add = len([h for h in hunk if h[0] == '+'])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   132
    rem = len([h for h in hunk if h[0] == '-'])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   133
    return add, rem
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   134
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   135
class hunk(object):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   136
    """patch hunk
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   137
    
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   138
    XXX shouldn't we merge this with patch.hunk ?
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   139
    """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   140
    maxcontext = 3
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   141
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   142
    def __init__(self, header, fromline, toline, proc, before, hunk, after):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   143
        def trimcontext(number, lines):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   144
            delta = len(lines) - self.maxcontext
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   145
            if False and delta > 0:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   146
                return number + delta, lines[:self.maxcontext]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   147
            return number, lines
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   148
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   149
        self.header = header
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   150
        self.fromline, self.before = trimcontext(fromline, before)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   151
        self.toline, self.after = trimcontext(toline, after)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   152
        self.proc = proc
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   153
        self.hunk = hunk
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   154
        self.added, self.removed = countchanges(self.hunk)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   155
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   156
    def write(self, fp):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   157
        delta = len(self.before) + len(self.after)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   158
        fromlen = delta + self.removed
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   159
        tolen = delta + self.added
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   160
        fp.write('@@ -%d,%d +%d,%d @@%s\n' %
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   161
                 (self.fromline, fromlen, self.toline, tolen,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   162
                  self.proc and (' ' + self.proc)))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   163
        fp.write(''.join(self.before + self.hunk + self.after))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   164
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   165
    pretty = write
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   166
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   167
    def filename(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   168
        return self.header.filename()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   169
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   170
    def __repr__(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   171
        return '<hunk %r@%d>' % (self.filename(), self.fromline)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   172
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   173
def parsepatch(fp):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   174
    """patch -> [] of hunks """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   175
    class parser(object):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   176
        """patch parsing state machine"""
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   177
        def __init__(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   178
            self.fromline = 0
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   179
            self.toline = 0
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   180
            self.proc = ''
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   181
            self.header = None
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   182
            self.context = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   183
            self.before = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   184
            self.hunk = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   185
            self.stream = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   186
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   187
        def addrange(self, (fromstart, fromend, tostart, toend, proc)):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   188
            self.fromline = int(fromstart)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   189
            self.toline = int(tostart)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   190
            self.proc = proc
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   191
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   192
        def addcontext(self, context):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   193
            if self.hunk:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   194
                h = hunk(self.header, self.fromline, self.toline, self.proc,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   195
                         self.before, self.hunk, context)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   196
                self.header.hunks.append(h)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   197
                self.stream.append(h)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   198
                self.fromline += len(self.before) + h.removed
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   199
                self.toline += len(self.before) + h.added
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   200
                self.before = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   201
                self.hunk = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   202
                self.proc = ''
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   203
            self.context = context
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   204
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   205
        def addhunk(self, hunk):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   206
            if self.context:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   207
                self.before = self.context
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   208
                self.context = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   209
            self.hunk = data
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   210
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   211
        def newfile(self, hdr):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   212
            self.addcontext([])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   213
            h = header(hdr)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   214
            self.stream.append(h)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   215
            self.header = h
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   216
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   217
        def finished(self):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   218
            self.addcontext([])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   219
            return self.stream
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   220
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   221
        transitions = {
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   222
            'file': {'context': addcontext,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   223
                     'file': newfile,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   224
                     'hunk': addhunk,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   225
                     'range': addrange},
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   226
            'context': {'file': newfile,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   227
                        'hunk': addhunk,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   228
                        'range': addrange},
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   229
            'hunk': {'context': addcontext,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   230
                     'file': newfile,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   231
                     'range': addrange},
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   232
            'range': {'context': addcontext,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   233
                      'hunk': addhunk},
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   234
            }
5143
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5129
diff changeset
   235
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   236
    p = parser()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   237
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   238
    state = 'context'
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   239
    for newstate, data in scanpatch(fp):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   240
        try:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   241
            p.transitions[state][newstate](p, data)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   242
        except KeyError:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   243
            raise patch.PatchError('unhandled transition: %s -> %s' %
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   244
                                   (state, newstate))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   245
        state = newstate
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   246
    return p.finished()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   247
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   248
def filterpatch(ui, chunks):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   249
    """Interactively filter patch chunks into applied-only chunks"""
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   250
    chunks = list(chunks)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   251
    chunks.reverse()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   252
    seen = {}
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   253
    def consumefile():
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   254
        """fetch next portion from chunks until a 'header' is seen
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   255
        NB: header == new-file mark
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   256
        """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   257
        consumed = []
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   258
        while chunks:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   259
            if isinstance(chunks[-1], header):
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   260
                break
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   261
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   262
                consumed.append(chunks.pop())
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   263
        return consumed
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   264
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   265
    resp_all = [None]   # this two are changed from inside prompt,
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   266
    resp_file = [None]  # so can't be usual variables
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   267
    applied = {}        # 'filename' -> [] of chunks
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   268
    def prompt(query):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   269
        """prompt query, and process base inputs
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   270
        
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   271
        - y/n for the rest of file
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   272
        - y/n for the rest
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   273
        - ? (help)
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   274
        - q (quit)
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   275
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   276
        else, input is returned to the caller.
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   277
        """
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   278
        if resp_all[0] is not None:
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   279
            return resp_all[0]
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   280
        if resp_file[0] is not None:
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   281
            return resp_file[0]
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   282
        while True:
5751
bc475d1f74ca prompt: kill matchflags
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5285
diff changeset
   283
            r = (ui.prompt(query + _(' [Ynsfdaq?] '), '(?i)[Ynsfdaq?]?$')
bc475d1f74ca prompt: kill matchflags
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5285
diff changeset
   284
                 or 'y').lower()
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   285
            if r == '?':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   286
                c = record.__doc__.find('y - record this change')
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   287
                for l in record.__doc__[c:].splitlines():
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   288
                    if l: ui.write(_(l.strip()), '\n')
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   289
                continue
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   290
            elif r == 's':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   291
                r = resp_file[0] = 'n'
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   292
            elif r == 'f':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   293
                r = resp_file[0] = 'y'
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   294
            elif r == 'd':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   295
                r = resp_all[0] = 'n'
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   296
            elif r == 'a':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   297
                r = resp_all[0] = 'y'
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   298
            elif r == 'q':
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   299
                raise util.Abort(_('user quit'))
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   300
            return r
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   301
    while chunks:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   302
        chunk = chunks.pop()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   303
        if isinstance(chunk, header):
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   304
            # new-file mark
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   305
            resp_file = [None]
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   306
            fixoffset = 0
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   307
            hdr = ''.join(chunk.header)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   308
            if hdr in seen:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   309
                consumefile()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   310
                continue
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   311
            seen[hdr] = True
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   312
            if resp_all[0] is None:
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   313
                chunk.pretty(ui)
5285
3ef190234b55 record: change wording of initial per-file prompt
Bryan O'Sullivan <bos@serpentine.com>
parents: 5154
diff changeset
   314
            r = prompt(_('examine changes to %s?') %
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   315
                       _(' and ').join(map(repr, chunk.files())))
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   316
            if r == 'y':
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   317
                applied[chunk.filename()] = [chunk]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   318
                if chunk.allhunks():
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   319
                    applied[chunk.filename()] += consumefile()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   320
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   321
                consumefile()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   322
        else:
5826
cc43d9f36ff2 record: some docs
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5751
diff changeset
   323
            # new hunk
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   324
            if resp_file[0] is None and resp_all[0] is None:
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   325
                chunk.pretty(ui)
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   326
            r = prompt(_('record this change to %r?') %
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   327
                       chunk.filename())
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   328
            if r == 'y':
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   329
                if fixoffset:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   330
                    chunk = copy.copy(chunk)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   331
                    chunk.toline += fixoffset
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   332
                applied[chunk.filename()].append(chunk)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   333
            else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   334
                fixoffset += chunk.removed - chunk.added
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   335
    return reduce(operator.add, [h for h in applied.itervalues()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   336
                                 if h[0].special() or len(h) > 1], [])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   337
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   338
def record(ui, repo, *pats, **opts):
5154
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   339
    '''interactively select changes to commit
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   340
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   341
    If a list of files is omitted, all changes reported by "hg status"
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   342
    will be candidates for recording.
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   343
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   344
    You will be prompted for whether to record changes to each
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   345
    modified file, and for files with multiple changes, for each
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   346
    change to use.  For each query, the following responses are
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   347
    possible:
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   348
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   349
    y - record this change
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   350
    n - skip this change
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   351
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   352
    s - skip remaining changes to this file
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   353
    f - record remaining changes to this file
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   354
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   355
    d - done, skip remaining changes and files
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   356
    a - record all changes to all remaining files
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   357
    q - quit, recording no changes
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   358
67afecb8d6cc record: improve docs, improve prompts
Bryan O'Sullivan <bos@serpentine.com>
parents: 5147
diff changeset
   359
    ? - display help'''
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   360
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   361
    def record_committer(ui, repo, pats, opts):
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   362
        commands.commit(ui, repo, *pats, **opts)
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   363
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   364
    dorecord(ui, repo, record_committer, *pats, **opts)
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   365
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   366
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   367
def qrecord(ui, repo, *pats, **opts):
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   368
    '''interactively select changes for qrefresh
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   369
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   370
    see 'hg help record' for more information and usage
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   371
    '''
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   372
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   373
    try:
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   374
        mq = extensions.find('mq')
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   375
    except KeyError:
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   376
        raise util.Abort(_("'mq' extension not loaded"))
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   377
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   378
    def qrecord_committer(ui, repo, pats, opts):
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   379
        mq.refresh(ui, repo, *pats, **opts)
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   380
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   381
    dorecord(ui, repo, qrecord_committer, *pats, **opts)
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   382
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   383
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   384
def dorecord(ui, repo, committer, *pats, **opts):
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   385
    if not ui.interactive:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   386
        raise util.Abort(_('running non-interactively, use commit instead'))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   387
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   388
    def recordfunc(ui, repo, files, message, match, opts):
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   389
        """This is generic record driver.
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   390
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   391
        It's job is to interactively filter local changes, and accordingly
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   392
        prepare working dir into a state, where the job can be delegated to
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   393
        non-interactive commit command such as 'commit' or 'qrefresh'.
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   394
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   395
        After the actual job is done by non-interactive command, working dir
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   396
        state is restored to original.
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   397
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   398
        In the end we'll record intresting changes, and everything else will be
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   399
        left in place, so the user can continue his work.
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   400
        """
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   401
        if files:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   402
            changes = None
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   403
        else:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   404
            changes = repo.status(files=files, match=match)[:5]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   405
            modified, added, removed = changes[:3]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   406
            files = modified + added + removed
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   407
        diffopts = mdiff.diffopts(git=True, nodates=True)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   408
        fp = cStringIO.StringIO()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   409
        patch.diff(repo, repo.dirstate.parents()[0], files=files,
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   410
                   match=match, changes=changes, opts=diffopts, fp=fp)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   411
        fp.seek(0)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   412
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   413
        # 1. filter patch, so we have intending-to apply subset of it
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   414
        chunks = filterpatch(ui, parsepatch(fp))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   415
        del fp
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   416
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   417
        contenders = {}
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   418
        for h in chunks:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   419
            try: contenders.update(dict.fromkeys(h.files()))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   420
            except AttributeError: pass
5143
d4fa6bafc43a Remove trailing spaces, fix indentation
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5129
diff changeset
   421
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   422
        newfiles = [f for f in files if f in contenders]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   423
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   424
        if not newfiles:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   425
            ui.status(_('no changes to record\n'))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   426
            return 0
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   427
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   428
        if changes is None:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   429
            changes = repo.status(files=newfiles, match=match)[:5]
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   430
        modified = dict.fromkeys(changes[0])
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   431
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   432
        # 2. backup changed files, so we can restore them in the end
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   433
        backups = {}
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   434
        backupdir = repo.join('record-backups')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   435
        try:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   436
            os.mkdir(backupdir)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   437
        except OSError, err:
5129
eca5b31cffc7 record: raise an exception correctly if we can't create a backup directory
Bryan O'Sullivan <bos@serpentine.com>
parents: 5128
diff changeset
   438
            if err.errno != errno.EEXIST:
eca5b31cffc7 record: raise an exception correctly if we can't create a backup directory
Bryan O'Sullivan <bos@serpentine.com>
parents: 5128
diff changeset
   439
                raise
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   440
        try:
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   441
            # backup continues
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   442
            for f in newfiles:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   443
                if f not in modified:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   444
                    continue
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   445
                fd, tmpname = tempfile.mkstemp(prefix=f.replace('/', '_')+'.',
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   446
                                               dir=backupdir)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   447
                os.close(fd)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   448
                ui.debug('backup %r as %r\n' % (f, tmpname))
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   449
                util.copyfile(repo.wjoin(f), tmpname)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   450
                backups[f] = tmpname
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   451
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   452
            fp = cStringIO.StringIO()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   453
            for c in chunks:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   454
                if c.filename() in backups:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   455
                    c.write(fp)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   456
            dopatch = fp.tell()
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   457
            fp.seek(0)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   458
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   459
            # 3a. apply filtered patch to clean repo  (clean)
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   460
            if backups:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   461
                hg.revert(repo, repo.dirstate.parents()[0], backups.has_key)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   462
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   463
            # 3b. (apply)
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   464
            if dopatch:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   465
                ui.debug('applying patch\n')
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   466
                ui.debug(fp.getvalue())
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   467
                patch.internalpatch(fp, ui, 1, repo.root)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   468
            del fp
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   469
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   470
            # 4. We prepared working directory according to filtered patch.
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   471
            #    Now is the time to delegate the job to commit/qrefresh or the like!
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   472
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   473
            # it is important to first chdir to repo root -- we'll call a
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   474
            # highlevel command with list of pathnames relative to repo root
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   475
            cwd = os.getcwd()
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   476
            os.chdir(repo.root)
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   477
            try:
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   478
                committer(ui, repo, newfiles, opts)
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   479
            finally:
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   480
                os.chdir(cwd)
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   481
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   482
            return 0
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   483
        finally:
5827
0c29977bd7db record: refactor record into generic record driver
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5826
diff changeset
   484
            # 5. finally restore backed-up files
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   485
            try:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   486
                for realname, tmpname in backups.iteritems():
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   487
                    ui.debug('restoring %r to %r\n' % (tmpname, realname))
5128
c9126c24e098 record: work properly if invoked in a subdirectory
Bryan O'Sullivan <bos@serpentine.com>
parents: 5040
diff changeset
   488
                    util.copyfile(tmpname, repo.wjoin(realname))
5037
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   489
                    os.unlink(tmpname)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   490
                os.rmdir(backupdir)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   491
            except OSError:
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   492
                pass
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   493
    return cmdutil.commit(ui, repo, recordfunc, pats, opts)
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   494
b2607267236d Add record extension, giving darcs-like interactive hunk picking
Bryan O'Sullivan <bos@serpentine.com>
parents:
diff changeset
   495
cmdtable = {
5040
4f34d9b2568e Update style of record's cmdtable to match mercurial/commands.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5037
diff changeset
   496
    "record":
4f34d9b2568e Update style of record's cmdtable to match mercurial/commands.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5037
diff changeset
   497
        (record,
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   498
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   499
         # add commit options
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   500
         commands.table['^commit|ci'][1],
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   501
5040
4f34d9b2568e Update style of record's cmdtable to match mercurial/commands.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5037
diff changeset
   502
         _('hg record [OPTION]... [FILE]...')),
4f34d9b2568e Update style of record's cmdtable to match mercurial/commands.py
Thomas Arendsen Hein <thomas@intevation.de>
parents: 5037
diff changeset
   503
}
5830
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   504
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   505
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   506
def extsetup():
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   507
    try:
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   508
        mq = extensions.find('mq')
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   509
    except KeyError:
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   510
        return
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   511
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   512
    qcmdtable = {
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   513
    "qrecord":
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   514
        (qrecord,
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   515
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   516
         # add qrefresh options
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   517
         mq.cmdtable['^qrefresh'][1],
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   518
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   519
         _('hg qrecord [OPTION]... [FILE]...')),
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   520
    }
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   521
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   522
    cmdtable.update(qcmdtable)
c32d41affb68 hg qrecord -- like record, but for mq
Kirill Smelkov <kirr@mns.spb.ru>
parents: 5827
diff changeset
   523