mercurial/changelog.py
author Sune Foldager <cryo@cyanite.org>
Thu, 12 May 2011 15:24:33 +0200
changeset 14301 f94993769c87
parent 14207 c1cca38818b9
child 14334 85c82ebc96a3
permissions -rw-r--r--
revlog: improve delta generation heuristics for generaldelta Without this change, pulls (and clones) into a generaldelta repository could generate very inefficient revlogs, the size of which could be at least twice the original size. This was caused by the generated delta chains covering too large distances, causing new chains to be built far too often. This change addresses the problem by forcing a delta against second parent or against the previous revision, when the first parent delta is in danger of creating a long chain.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1095
0a18374c0769 changelog: adjust imports, comment
mpm@selenic.com
parents: 1094 1089
diff changeset
     1
# changelog.py - changelog class for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4269
diff changeset
     3
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9677
diff changeset
     6
# GNU General Public License version 2 or any later version.
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     7
6211
f89fd07fc51d Expand import * to allow Pyflakes to find problems
Joel Rosdahl <joel@rosdahl.net>
parents: 5791
diff changeset
     8
from node import bin, hex, nullid
7035
9d023ef7b467 forbid username with '\n' at the changelog level
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6259
diff changeset
     9
from i18n import _
7948
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7807
diff changeset
    10
import util, error, revlog, encoding
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    11
3232
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    12
def _string_escape(text):
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    13
    """
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    14
    >>> d = {'nl': chr(10), 'bs': chr(92), 'cr': chr(13), 'nul': chr(0)}
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    15
    >>> s = "ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    16
    >>> s
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    17
    'ab\\ncd\\\\\\\\n\\x00ab\\rcd\\\\\\n'
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    18
    >>> res = _string_escape(s)
5745
234e40e636a8 changelog: inline trivial call for extra data unescaping
Matt Mackall <mpm@selenic.com>
parents: 5744
diff changeset
    19
    >>> s == res.decode('string_escape')
3232
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    20
    True
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    21
    """
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    22
    # subset of the string_escape codec
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    23
    text = text.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r')
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    24
    return text.replace('\0', '\\0')
394ac87f3b74 [extendedchangelog] encode/decode function
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3077
diff changeset
    25
8443
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    26
def decodeextra(text):
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    27
    extra = {}
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    28
    for l in text.split('\0'):
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    29
        if l:
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    30
            k, v = l.decode('string_escape').split(':', 1)
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    31
            extra[k] = v
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    32
    return extra
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    33
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    34
def encodeextra(d):
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    35
    # keys must be sorted to produce a deterministic changelog entry
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    36
    items = [_string_escape('%s:%s' % (k, d[k])) for k in sorted(d)]
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    37
    return "\0".join(items)
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
    38
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8644
diff changeset
    39
class appender(object):
7807
bd8f44638847 help: miscellaneous language fixes
timeless <timeless@gmail.com>
parents: 7787
diff changeset
    40
    '''the changelog index must be updated last on disk, so we use this class
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    41
    to delay writes to it'''
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    42
    def __init__(self, fp, buf):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    43
        self.data = buf
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    44
        self.fp = fp
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    45
        self.offset = fp.tell()
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    46
        self.size = util.fstat(fp).st_size
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    47
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    48
    def end(self):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    49
        return self.size + len("".join(self.data))
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    50
    def tell(self):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    51
        return self.offset
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    52
    def flush(self):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    53
        pass
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    54
    def close(self):
4961
3fdd09ad6cce fix bogus close spotted by pychecker (no close() in global scope)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 4635
diff changeset
    55
        self.fp.close()
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    56
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    57
    def seek(self, offset, whence=0):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    58
        '''virtual file offset spans real file and data'''
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    59
        if whence == 0:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    60
            self.offset = offset
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    61
        elif whence == 1:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    62
            self.offset += offset
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    63
        elif whence == 2:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    64
            self.offset = self.end() + offset
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    65
        if self.offset < self.size:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    66
            self.fp.seek(self.offset)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    67
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    68
    def read(self, count=-1):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    69
        '''only trick here is reads that span real file and data'''
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    70
        ret = ""
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    71
        if self.offset < self.size:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    72
            s = self.fp.read(count)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    73
            ret = s
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    74
            self.offset += len(s)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    75
            if count > 0:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    76
                count -= len(s)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    77
        if count != 0:
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    78
            doff = self.offset - self.size
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    79
            self.data.insert(0, "".join(self.data))
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    80
            del self.data[1:]
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    81
            s = self.data[0][doff:doff + count]
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    82
            self.offset += len(s)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    83
            ret += s
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    84
        return ret
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    85
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    86
    def write(self, s):
5450
c728424d44c6 revlog: fix caching of buffer objects
Matt Mackall <mpm@selenic.com>
parents: 4963
diff changeset
    87
        self.data.append(str(s))
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    88
        self.offset += len(s)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
    89
9166
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    90
def delayopener(opener, target, divert, buf):
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    91
    def o(name, mode='r'):
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    92
        if name != target:
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    93
            return opener(name, mode)
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    94
        if divert:
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    95
            return opener(name + ".a", mode.replace('a', 'w'))
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    96
        # otherwise, divert to memory
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    97
        return appender(opener(name, mode), buf)
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    98
    return o
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
    99
7634
14a4337a9b9b revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents: 7633
diff changeset
   100
class changelog(revlog.revlog):
4258
b11a2fb59cf5 revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents: 4257
diff changeset
   101
    def __init__(self, opener):
9165
07f9b2f4a9aa changelog: swap opener to switch delay modes
Matt Mackall <mpm@selenic.com>
parents: 9164
diff changeset
   102
        revlog.revlog.__init__(self, opener, "00changelog.i")
8644
c2ef478b2efa changelog: make delayopener less intrusive
Matt Mackall <mpm@selenic.com>
parents: 8499
diff changeset
   103
        self._realopener = opener
c2ef478b2efa changelog: make delayopener less intrusive
Matt Mackall <mpm@selenic.com>
parents: 8499
diff changeset
   104
        self._delayed = False
9163
f193b643d1b1 changelog: _delaycount -> _divert
Matt Mackall <mpm@selenic.com>
parents: 8778
diff changeset
   105
        self._divert = False
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   106
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   107
    def delayupdate(self):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   108
        "delay visibility of index updates to other readers"
8644
c2ef478b2efa changelog: make delayopener less intrusive
Matt Mackall <mpm@selenic.com>
parents: 8499
diff changeset
   109
        self._delayed = True
9163
f193b643d1b1 changelog: _delaycount -> _divert
Matt Mackall <mpm@selenic.com>
parents: 8778
diff changeset
   110
        self._divert = (len(self) == 0)
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   111
        self._delaybuf = []
9166
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
   112
        self.opener = delayopener(self._realopener, self.indexfile,
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
   113
                                  self._divert, self._delaybuf)
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   114
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   115
    def finalize(self, tr):
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   116
        "finalize index updates"
8644
c2ef478b2efa changelog: make delayopener less intrusive
Matt Mackall <mpm@selenic.com>
parents: 8499
diff changeset
   117
        self._delayed = False
9165
07f9b2f4a9aa changelog: swap opener to switch delay modes
Matt Mackall <mpm@selenic.com>
parents: 9164
diff changeset
   118
        self.opener = self._realopener
4269
73c918c71300 changelog: optimize delayed updates for clone vs pull
Matt Mackall <mpm@selenic.com>
parents: 4261
diff changeset
   119
        # move redirected index data back into place
9164
b0d995b6b0a6 changelog: factor out _delayname
Matt Mackall <mpm@selenic.com>
parents: 9163
diff changeset
   120
        if self._divert:
14207
c1cca38818b9 changelog: fixes leaked file handle
Zachary Gramana <zgramana@pottsconsultinggroup.com>
parents: 14004
diff changeset
   121
            nfile = self.opener(self.indexfile + ".a")
c1cca38818b9 changelog: fixes leaked file handle
Zachary Gramana <zgramana@pottsconsultinggroup.com>
parents: 14004
diff changeset
   122
            n = nfile.name
c1cca38818b9 changelog: fixes leaked file handle
Zachary Gramana <zgramana@pottsconsultinggroup.com>
parents: 14004
diff changeset
   123
            nfile.close()
9166
e6162b854ed5 changelog: move delayopener outside of class to eliminate reference cycle
Matt Mackall <mpm@selenic.com>
parents: 9165
diff changeset
   124
            util.rename(n, n[:-2])
4269
73c918c71300 changelog: optimize delayed updates for clone vs pull
Matt Mackall <mpm@selenic.com>
parents: 4261
diff changeset
   125
        elif self._delaybuf:
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   126
            fp = self.opener(self.indexfile, 'a')
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   127
            fp.write("".join(self._delaybuf))
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   128
            fp.close()
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   129
            self._delaybuf = []
4269
73c918c71300 changelog: optimize delayed updates for clone vs pull
Matt Mackall <mpm@selenic.com>
parents: 4261
diff changeset
   130
        # split when we're done
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   131
        self.checkinlinesize(tr)
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   132
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   133
    def readpending(self, file):
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   134
        r = revlog.revlog(self.opener, file)
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   135
        self.index = r.index
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   136
        self.nodemap = r.nodemap
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   137
        self._chunkcache = r._chunkcache
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   138
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   139
    def writepending(self):
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   140
        "create a file containing the unfinalized state for pretxnchangegroup"
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   141
        if self._delaybuf:
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   142
            # make a temporary copy of the index
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   143
            fp1 = self._realopener(self.indexfile)
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   144
            fp2 = self._realopener(self.indexfile + ".a", "w")
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   145
            fp2.write(fp1.read())
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   146
            # add pending data
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   147
            fp2.write("".join(self._delaybuf))
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   148
            fp2.close()
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   149
            # switch modes so finalize can simply rename
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   150
            self._delaybuf = []
9164
b0d995b6b0a6 changelog: factor out _delayname
Matt Mackall <mpm@selenic.com>
parents: 9163
diff changeset
   151
            self._divert = True
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   152
9164
b0d995b6b0a6 changelog: factor out _delayname
Matt Mackall <mpm@selenic.com>
parents: 9163
diff changeset
   153
        if self._divert:
7787
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   154
            return True
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   155
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   156
        return False
b8d750daadde Introduce HG_PREPEND to solve pretxn races
Matt Mackall <mpm@selenic.com>
parents: 7634
diff changeset
   157
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   158
    def checkinlinesize(self, tr, fp=None):
9165
07f9b2f4a9aa changelog: swap opener to switch delay modes
Matt Mackall <mpm@selenic.com>
parents: 9164
diff changeset
   159
        if not self._delayed:
07f9b2f4a9aa changelog: swap opener to switch delay modes
Matt Mackall <mpm@selenic.com>
parents: 9164
diff changeset
   160
            revlog.revlog.checkinlinesize(self, tr, fp)
4261
cd7b36b7869c restructure changelog file appending
Matt Mackall <mpm@selenic.com>
parents: 4258
diff changeset
   161
5744
9db7fd77417d changelog: remove extract function
Matt Mackall <mpm@selenic.com>
parents: 5450
diff changeset
   162
    def read(self, node):
3077
ad6aecaf4eed document changelog format
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   163
        """
ad6aecaf4eed document changelog format
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   164
        format used:
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   165
        nodeid\n        : manifest node in ascii
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   166
        user\n          : user, no \n or \r allowed
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   167
        time tz extra\n : date (time is int or float, timezone is int)
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   168
                        : extra is metadatas, encoded and separated by '\0'
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   169
                        : older versions ignore it
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   170
        files\n\n       : files modified by the cset, no \n or \r allowed
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   171
        (.*)            : comment (free text, ideally utf-8)
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   172
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   173
        changelog v0 doesn't use extra
3077
ad6aecaf4eed document changelog format
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   174
        """
5744
9db7fd77417d changelog: remove extract function
Matt Mackall <mpm@selenic.com>
parents: 5450
diff changeset
   175
        text = self.revision(node)
37
a8811676c85a Move hex/bin bits to revlog
mpm@selenic.com
parents: 33
diff changeset
   176
        if not text:
4176
f9bbcebcacea "default" is the default branch name
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3771
diff changeset
   177
            return (nullid, "", (0, 0), [], "", {'branch': 'default'})
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   178
        last = text.index("\n\n")
7948
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7807
diff changeset
   179
        desc = encoding.tolocal(text[last + 2:])
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   180
        l = text[:last].split('\n')
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   181
        manifest = bin(l[0])
7948
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7807
diff changeset
   182
        user = encoding.tolocal(l[1])
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   183
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   184
        extra_data = l[2].split(' ', 2)
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   185
        if len(extra_data) != 3:
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   186
            time = float(extra_data.pop(0))
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   187
            try:
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   188
                # various tools did silly things with the time zone field.
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   189
                timezone = int(extra_data[0])
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 10420
diff changeset
   190
            except ValueError:
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   191
                timezone = 0
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   192
            extra = {}
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   193
        else:
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   194
            time, timezone, extra = extra_data
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   195
            time, timezone = float(time), int(timezone)
8443
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
   196
            extra = decodeextra(extra)
4176
f9bbcebcacea "default" is the default branch name
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3771
diff changeset
   197
        if not extra.get('branch'):
f9bbcebcacea "default" is the default branch name
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3771
diff changeset
   198
            extra['branch'] = 'default'
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   199
        files = l[3:]
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   200
        return (manifest, user, (time, timezone), files, desc, extra)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   201
8422
437e06bbd11e changelog: removed bad default arguments in add method
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
   202
    def add(self, manifest, files, desc, transaction, p1, p2,
9677
0c072e63e3e7 changelog: do not use a mutable default value
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9166
diff changeset
   203
                  user, date=None, extra=None):
7035
9d023ef7b467 forbid username with '\n' at the changelog level
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6259
diff changeset
   204
        user = user.strip()
8424
c5b3d3e30de7 changelog: refuse to add revisions with empty usernames
Martin Geisler <mg@lazybytes.net>
parents: 7807
diff changeset
   205
        # An empty username or a username with a "\n" will make the
c5b3d3e30de7 changelog: refuse to add revisions with empty usernames
Martin Geisler <mg@lazybytes.net>
parents: 7807
diff changeset
   206
        # revision text contain two "\n\n" sequences -> corrupt
c5b3d3e30de7 changelog: refuse to add revisions with empty usernames
Martin Geisler <mg@lazybytes.net>
parents: 7807
diff changeset
   207
        # repository since read cannot unpack the revision.
c5b3d3e30de7 changelog: refuse to add revisions with empty usernames
Martin Geisler <mg@lazybytes.net>
parents: 7807
diff changeset
   208
        if not user:
c5b3d3e30de7 changelog: refuse to add revisions with empty usernames
Martin Geisler <mg@lazybytes.net>
parents: 7807
diff changeset
   209
            raise error.RevlogError(_("empty username"))
7035
9d023ef7b467 forbid username with '\n' at the changelog level
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 6259
diff changeset
   210
        if "\n" in user:
7633
08cabecfa8a8 errors: move revlog errors
Matt Mackall <mpm@selenic.com>
parents: 7470
diff changeset
   211
            raise error.RevlogError(_("username %s contains a newline")
08cabecfa8a8 errors: move revlog errors
Matt Mackall <mpm@selenic.com>
parents: 7470
diff changeset
   212
                                    % repr(user))
8499
fb9b83df45f3 commit: move description trimming into changelog
Matt Mackall <mpm@selenic.com>
parents: 8443
diff changeset
   213
fb9b83df45f3 commit: move description trimming into changelog
Matt Mackall <mpm@selenic.com>
parents: 8443
diff changeset
   214
        # strip trailing whitespace and leading and trailing empty lines
fb9b83df45f3 commit: move description trimming into changelog
Matt Mackall <mpm@selenic.com>
parents: 8443
diff changeset
   215
        desc = '\n'.join([l.rstrip() for l in desc.splitlines()]).strip('\n')
fb9b83df45f3 commit: move description trimming into changelog
Matt Mackall <mpm@selenic.com>
parents: 8443
diff changeset
   216
7948
de377b1a9a84 move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents: 7807
diff changeset
   217
        user, desc = encoding.fromlocal(user), encoding.fromlocal(desc)
3771
29d91e57d055 Handle transcoding of username and description in changelog
Matt Mackall <mpm@selenic.com>
parents: 3412
diff changeset
   218
1195
f92af8d53330 Validate user input of dates when adding a changelog entry.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1095
diff changeset
   219
        if date:
2523
4ab59a3acd16 validate the resulting date in parsedate
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2522
diff changeset
   220
            parseddate = "%d %d" % util.parsedate(date)
1195
f92af8d53330 Validate user input of dates when adding a changelog entry.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1095
diff changeset
   221
        else:
2522
85f796baab10 Allow the use of human readable dates (issue 251)
Jose M. Prieto <jmprieto@gmx.net>
parents: 2142
diff changeset
   222
            parseddate = "%d %d" % util.makedate()
10417
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   223
        if extra:
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   224
            branch = extra.get("branch")
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   225
            if branch in ("default", ""):
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   226
                del extra["branch"]
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   227
            elif branch in (".", "null", "tip"):
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   228
                raise error.RevlogError(_('the name \'%s\' is reserved')
58e040c51231 branch: avoid using reserved tag names
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 10263
diff changeset
   229
                                        % branch)
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   230
        if extra:
8443
53ff4a5af284 changelog: turn {de,en}code_extra methods into functions
Martin Geisler <mg@lazybytes.net>
parents: 8442
diff changeset
   231
            extra = encodeextra(extra)
3233
2f35961854fb [extendedchangelog] add extra metadata in the changelog entry
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 3232
diff changeset
   232
            parseddate = "%s %s" % (parseddate, extra)
8209
a1a5a57efe90 replace util.sort with sorted built-in
Matt Mackall <mpm@selenic.com>
parents: 7948
diff changeset
   233
        l = [hex(manifest), user, parseddate] + sorted(files) + ["", desc]
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   234
        text = "\n".join(l)
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6259
diff changeset
   235
        return self.addrevision(text, transaction, len(self), p1, p2)