mercurial/transaction.py
author Gregory Szorc <gregory.szorc@gmail.com>
Fri, 26 May 2017 13:27:21 -0700
changeset 32558 aa91085cadf3
parent 32291 bd872f64a8ba
child 33056 2312e70cf78b
permissions -rw-r--r--
transaction: delete callbacks after use Before this change, localrepository instances that performed multiple transactions would leak transaction objects. This could occur when running `hg convert`. When running `hg convert`, the leak would be ~90 MB per 10,000 changesets as measured with the Mercurial repo itself. The leak I tracked down involved the "validate" closure from localrepository.transaction(). It appeared to be keeping a reference to the original transaction via __closure__. __del__ semantics and a circular reference involving the repo object may have also come into play. Attempting to refactor the "validate" closure proved to be difficult because the "tr" reference in that closure may reference an object that isn't created until transaction.__init__ is called. And the "validate" closure is passed as an argument to transaction.__init__. Plus there is a giant warning comment in "validate" about how hacky it is. I did not want to venture into the dragon den. Anyway, we've had problems with transactions causing leaks before. The solution then (14e683d6b273) is the same as the solution in this patch: drop references to callbacks after they are called. This not only breaks cycles in core Mercurial but can help break cycles in extensions that accidentally introduce them. While I only tracked down a leak due to self.validator, since this is the 2nd time I've tracked down leaks due to transaction callbacks I figure enough is enough and we should prevent the class of leak from occurring regardless of the variable. That's why all callback variables are now nuked.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17424
e7cfe3587ea4 fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents: 16689
diff changeset
     1
# transaction.py - simple journaling scheme for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     3
# This transaction scheme is intended to gracefully handle program
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     4
# errors and interruptions. More serious failures like system crashes
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     5
# can be recovered with an fsck-like tool. As the whole repository is
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     6
# effectively log-structured, this should amount to simply truncating
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     7
# anything that isn't referenced in the changelog.
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     8
#
2859
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2470
diff changeset
     9
# Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    10
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8071
diff changeset
    11
# 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: 10228
diff changeset
    12
# 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
    13
25986
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    14
from __future__ import absolute_import
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    15
20886
203908968644 transaction: drop extra import caught by pyflakes
Matt Mackall <mpm@selenic.com>
parents: 20882
diff changeset
    16
import errno
25986
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    17
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    18
from .i18n import _
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    19
from . import (
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    20
    error,
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    21
    util,
89049011f304 transaction: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25660
diff changeset
    22
)
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    23
23313
991098579940 transaction: set backupentries version to proper value
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23312
diff changeset
    24
version = 2
23064
5dc888b79e70 transactions: add version number to journal.backupfiles
Durham Goode <durham@fb.com>
parents: 23063
diff changeset
    25
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    26
# These are the file generators that should only be executed after the
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    27
# finalizers are done, since they rely on the output of the finalizers (like
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    28
# the changelog having been written).
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32261
diff changeset
    29
postfinalizegenerators = {
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    30
    'bookmarks',
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    31
    'dirstate'
32291
bd872f64a8ba cleanup: use set literals
Martin von Zweigbergk <martinvonz@google.com>
parents: 32261
diff changeset
    32
}
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    33
29297
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
    34
gengroupall='all'
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
    35
gengroupprefinalize='prefinalize'
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
    36
gengrouppostfinalize='postfinalize'
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
    37
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    38
def active(func):
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    39
    def _active(self, *args, **kwds):
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    40
        if self.count == 0:
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    41
            raise error.Abort(_(
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    42
                'cannot use transaction when it is already committed/aborted'))
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    43
        return func(self, *args, **kwds)
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    44
    return _active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    45
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
    46
def _playback(journal, report, opener, vfsmap, entries, backupentries,
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
    47
              unlink=True):
22204
f8dc6599da5d cleanup: name unused variables using convention of leading _
Mads Kiilerich <madski@unity3d.com>
parents: 22199
diff changeset
    48
    for f, o, _ignore in entries:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    49
        if o or not unlink:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    50
            try:
30002
599912a62ff6 transaction: open a file with checkambig=True to avoid file stat ambiguity
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29353
diff changeset
    51
                fp = opener(f, 'a', checkambig=True)
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
    52
                fp.truncate(o)
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
    53
                fp.close()
9686
ddf2adf88b89 transaction: more specific exceptions, os.unlink can raise OSError
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9220
diff changeset
    54
            except IOError:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    55
                report(_("failed to truncate %s\n") % f)
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    56
                raise
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    57
        else:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    58
            try:
20084
a3378a1b0a05 transaction: unlink target file via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17424
diff changeset
    59
                opener.unlink(f)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
    60
            except (IOError, OSError) as inst:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    61
                if inst.errno != errno.ENOENT:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    62
                    raise
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    63
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    64
    backupfiles = []
23309
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
    65
    for l, f, b, c in backupentries:
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    66
        if l not in vfsmap and c:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    67
            report("couldn't handle %s: unknown cache location %s\n"
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    68
                        % (b, l))
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
    69
        vfs = vfsmap[l]
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    70
        try:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    71
            if f and b:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    72
                filepath = vfs.join(f)
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    73
                backuppath = vfs.join(b)
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    74
                try:
29353
a9ccd9af48ef transaction: avoid ambiguity of file stat at restoring from backup
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29299
diff changeset
    75
                    util.copyfile(backuppath, filepath, checkambig=True)
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    76
                    backupfiles.append(b)
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    77
                except IOError:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    78
                    report(_("failed to recover %s\n") % f)
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    79
            else:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    80
                target = f or b
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    81
                try:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    82
                    vfs.unlink(target)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25658
diff changeset
    83
                except (IOError, OSError) as inst:
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    84
                    if inst.errno != errno.ENOENT:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    85
                        raise
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26576
diff changeset
    86
        except (IOError, OSError, error.Abort) as inst:
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    87
            if not c:
23278
aa19432764d6 transaction: handle missing file in backupentries (instead of using entries)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23253
diff changeset
    88
                raise
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    89
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    90
    backuppath = "%s.backupfiles" % journal
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    91
    if opener.exists(backuppath):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    92
        opener.unlink(backuppath)
26753
96dd93de548c transaction: reorder unlinking .hg/journal and .hg/journal.backupfiles
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26587
diff changeset
    93
    opener.unlink(journal)
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    94
    try:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    95
        for f in backupfiles:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    96
            if opener.exists(f):
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    97
                opener.unlink(f)
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26576
diff changeset
    98
    except (IOError, OSError, error.Abort) as inst:
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
    99
        # only pure backup file remains, it is sage to ignore any error
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   100
        pass
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   101
1559
59b3639df0a9 Convert all classes to new-style classes by deriving them from object.
Eric Hopper <hopper@omnifarious.org>
parents: 1541
diff changeset
   102
class transaction(object):
23903
426607be9c69 transaction: pass the name of the "undo" journal to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23901
diff changeset
   103
    def __init__(self, report, opener, vfsmap, journalname, undoname=None,
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   104
                 after=None, createmode=None, validator=None, releasefn=None):
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   105
        """Begin a new transaction
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   106
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   107
        Begins a new transaction that allows rolling back writes in the event of
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   108
        an exception.
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   109
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   110
        * `after`: called after the transaction has been committed
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   111
        * `createmode`: the mode of the journal file that will be created
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   112
        * `releasefn`: called after releasing (with transaction and result)
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   113
        """
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   114
        self.count = 1
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   115
        self.usages = 1
582
df8a5a0098d4 Remove all remaining print statements
mpm@selenic.com
parents: 573
diff changeset
   116
        self.report = report
23310
5bd1f6572db0 transaction: pass a vfs map to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23309
diff changeset
   117
        # a vfs to the store content
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   118
        self.opener = opener
23310
5bd1f6572db0 transaction: pass a vfs map to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23309
diff changeset
   119
        # a map to access file in various {location -> vfs}
5bd1f6572db0 transaction: pass a vfs map to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23309
diff changeset
   120
        vfsmap = vfsmap.copy()
5bd1f6572db0 transaction: pass a vfs map to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23309
diff changeset
   121
        vfsmap[''] = opener  # set default value
5bd1f6572db0 transaction: pass a vfs map to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23309
diff changeset
   122
        self._vfsmap = vfsmap
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
   123
        self.after = after
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   124
        self.entries = []
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   125
        self.map = {}
23901
13268fde4c4d transaction: clarify the name of 'journal' argument for transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23900
diff changeset
   126
        self.journal = journalname
23903
426607be9c69 transaction: pass the name of the "undo" journal to the transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23901
diff changeset
   127
        self.undoname = undoname
23279
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   128
        self._queue = []
24283
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   129
        # A callback to validate transaction content before closing it.
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   130
        # should raise exception is anything is wrong.
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   131
        # target user is repository hooks.
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   132
        if validator is None:
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   133
            validator = lambda tr: None
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   134
        self.validator = validator
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   135
        # A callback to do something just after releasing transaction.
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   136
        if releasefn is None:
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   137
            releasefn = lambda tr, success: None
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   138
        self.releasefn = releasefn
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   139
32261
976681123416 transaction: introduce "changes" dictionary to precisely track updates
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31648
diff changeset
   140
        # A dict dedicated to precisely tracking the changes introduced in the
976681123416 transaction: introduce "changes" dictionary to precisely track updates
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31648
diff changeset
   141
        # transaction.
976681123416 transaction: introduce "changes" dictionary to precisely track updates
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31648
diff changeset
   142
        self.changes = {}
976681123416 transaction: introduce "changes" dictionary to precisely track updates
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31648
diff changeset
   143
23279
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   144
        # a dict of arguments to be passed to hooks
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   145
        self.hookargs = {}
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   146
        self.file = opener.open(self.journal, "w")
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   147
23309
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
   148
        # a list of ('location', 'path', 'backuppath', cache) entries.
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   149
        # - if 'backuppath' is empty, no file existed at backup time
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   150
        # - if 'path' is empty, this is a temporary transaction file
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   151
        # - if 'location' is not empty, the path is outside main opener reach.
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   152
        #   use 'location' value as a key in a vfsmap to find the right 'vfs'
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   153
        # (cache is currently unused)
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   154
        self._backupentries = []
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   155
        self._backupmap = {}
23901
13268fde4c4d transaction: clarify the name of 'journal' argument for transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23900
diff changeset
   156
        self._backupjournal = "%s.backupfiles" % self.journal
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   157
        self._backupsfile = opener.open(self._backupjournal, 'w')
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   158
        self._backupsfile.write('%d\n' % version)
23279
e245775f8fd3 transaction: gather backupjournal logic together in the __init__
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23278
diff changeset
   159
6065
53ed9b40cfc4 make the journal/undo files from transactions inherit the mode from .hg/store
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5865
diff changeset
   160
        if createmode is not None:
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25302
diff changeset
   161
            opener.chmod(self.journal, createmode & 0o666)
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25302
diff changeset
   162
            opener.chmod(self._backupjournal, createmode & 0o666)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   163
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   164
        # hold file generations to be performed on commit
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   165
        self._filegenerators = {}
23543
4dd8a6a1240d spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23513
diff changeset
   166
        # hold callback to write pending data for hooks
23202
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   167
        self._pendingcallback = {}
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   168
        # True is any pending data have been written ever
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   169
        self._anypending = False
23204
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   170
        # holds callback to call when writing the transaction
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   171
        self._finalizecallback = {}
23543
4dd8a6a1240d spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23513
diff changeset
   172
        # hold callback for post transaction close
23220
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   173
        self._postclosecallback = {}
23764
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   174
        # holds callbacks to call during abort
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   175
        self._abortcallback = {}
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   176
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   177
    def __del__(self):
558
0ceea19182a9 transaction: __del__ should do nothing if the journal already exists
mpm@selenic.com
parents: 515
diff changeset
   178
        if self.journal:
9693
c40a1ee20aa5 transaction: always remove empty journal on abort
Sune Foldager <cryo@cyanite.org>
parents: 9686
diff changeset
   179
            self._abort()
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   180
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   181
    @active
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   182
    def startgroup(self):
23250
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   183
        """delay registration of file entry
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   184
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   185
        This is used by strip to delay vision of strip offset. The transaction
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   186
        sees either none or all of the strip actions to be done."""
23251
85c634ff395a transaction: drop backupentries logic from startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23250
diff changeset
   187
        self._queue.append([])
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   188
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   189
    @active
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   190
    def endgroup(self):
23250
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   191
        """apply delayed registration of file entry.
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   192
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   193
        This is used by strip to delay vision of strip offset. The transaction
8919dc7f2dbb transaction: document startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23249
diff changeset
   194
        sees either none or all of the strip actions to be done."""
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   195
        q = self._queue.pop()
23253
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   196
        for f, o, data in q:
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   197
            self._addentry(f, o, data)
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   198
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   199
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   200
    def add(self, file, offset, data=None):
23252
70809438c644 transaction: document `tr.add`
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23251
diff changeset
   201
        """record the state of an append-only file before update"""
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   202
        if file in self.map or file in self._backupmap:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   203
            return
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   204
        if self._queue:
23251
85c634ff395a transaction: drop backupentries logic from startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23250
diff changeset
   205
            self._queue[-1].append((file, offset, data))
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   206
            return
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   207
23253
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   208
        self._addentry(file, offset, data)
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   209
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   210
    def _addentry(self, file, offset, data):
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   211
        """add a append-only entry to memory and on-disk state"""
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   212
        if file in self.map or file in self._backupmap:
8d84b7a2dd91 transaction: factorise append-only file registration
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23252
diff changeset
   213
            return
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   214
        self.entries.append((file, offset, data))
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   215
        self.map[file] = len(self.entries) - 1
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   216
        # add enough data to the journal to do the truncate
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   217
        self.file.write("%s\0%d\n" % (file, offset))
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   218
        self.file.flush()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   219
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   220
    @active
23316
fc3670f41d3e transaction: use 'location' instead of 'vfs' in the addbackup method
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23315
diff changeset
   221
    def addbackup(self, file, hardlink=True, location=''):
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   222
        """Adds a backup of the file to the transaction
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   223
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   224
        Calling addbackup() creates a hardlink backup of the specified file
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   225
        that is used to recover the file in the event of the transaction
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   226
        aborting.
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   227
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   228
        * `file`: the file path, relative to .hg/store
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   229
        * `hardlink`: use a hardlink to quickly create the backup
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   230
        """
23251
85c634ff395a transaction: drop backupentries logic from startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23250
diff changeset
   231
        if self._queue:
85c634ff395a transaction: drop backupentries logic from startgroup and endgroup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23250
diff changeset
   232
            msg = 'cannot use transaction.addbackup inside "group"'
31648
8defc7d9adae transaction: use ProgrammingError
Jun Wu <quark@fb.com>
parents: 30002
diff changeset
   233
            raise error.ProgrammingError(msg)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   234
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   235
        if file in self.map or file in self._backupmap:
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   236
            return
23582
7559dc8c4238 vfs: add a 'split' method
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23581
diff changeset
   237
        vfs = self._vfsmap[location]
7559dc8c4238 vfs: add a 'split' method
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23581
diff changeset
   238
        dirname, filename = vfs.split(file)
23315
66275ecc73c1 addbackup: handle file in subdirectory
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23314
diff changeset
   239
        backupfilename = "%s.backup.%s" % (self.journal, filename)
23581
aed981c7bebf vfs: add a 'reljoin' function for joining relative paths
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23543
diff changeset
   240
        backupfile = vfs.reljoin(dirname, backupfilename)
22663
4c6198737ad8 transaction: allow generating file outside of store
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22662
diff changeset
   241
        if vfs.exists(file):
4c6198737ad8 transaction: allow generating file outside of store
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22662
diff changeset
   242
            filepath = vfs.join(file)
23314
43f66ae57a66 addbackup: use the vfs for the backup destination too
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23313
diff changeset
   243
            backuppath = vfs.join(backupfile)
23900
5eb3541f907e transaction: use 'util.copyfile' for creating backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23764
diff changeset
   244
            util.copyfile(filepath, backuppath, hardlink=hardlink)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   245
        else:
23278
aa19432764d6 transaction: handle missing file in backupentries (instead of using entries)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23253
diff changeset
   246
            backupfile = ''
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   247
23316
fc3670f41d3e transaction: use 'location' instead of 'vfs' in the addbackup method
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23315
diff changeset
   248
        self._addbackupentry((location, file, backupfile, False))
23283
b04263c38a92 transaction: extract backupentry registration in a dedicated function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23282
diff changeset
   249
b04263c38a92 transaction: extract backupentry registration in a dedicated function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23282
diff changeset
   250
    def _addbackupentry(self, entry):
b04263c38a92 transaction: extract backupentry registration in a dedicated function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23282
diff changeset
   251
        """register a new backup entry and write it to disk"""
b04263c38a92 transaction: extract backupentry registration in a dedicated function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23282
diff changeset
   252
        self._backupentries.append(entry)
25294
b1b89a0a606d transaction: really fix _addbackupentry key usage (issue4684)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25263
diff changeset
   253
        self._backupmap[entry[1]] = len(self._backupentries) - 1
23309
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
   254
        self._backupsfile.write("%s\0%s\0%s\0%d\n" % entry)
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   255
        self._backupsfile.flush()
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   256
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   257
    @active
23354
918c77775df6 transaction: accept a 'location' argument for registertmp
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23318
diff changeset
   258
    def registertmp(self, tmpfile, location=''):
23291
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   259
        """register a temporary transaction file
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   260
23355
7faa55c20b0e transaction: fix some docstring grammar
Matt Mackall <mpm@selenic.com>
parents: 23354
diff changeset
   261
        Such files will be deleted when the transaction exits (on both
7faa55c20b0e transaction: fix some docstring grammar
Matt Mackall <mpm@selenic.com>
parents: 23354
diff changeset
   262
        failure and success).
23291
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   263
        """
23354
918c77775df6 transaction: accept a 'location' argument for registertmp
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23318
diff changeset
   264
        self._addbackupentry((location, '', tmpfile, False))
23291
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   265
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   266
    @active
23317
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   267
    def addfilegenerator(self, genid, filenames, genfunc, order=0,
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   268
                         location=''):
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   269
        """add a function to generates some files at transaction commit
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   270
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   271
        The `genfunc` argument is a function capable of generating proper
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   272
        content of each entry in the `filename` tuple.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   273
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   274
        At transaction close time, `genfunc` will be called with one file
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   275
        object argument per entries in `filenames`.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   276
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   277
        The transaction itself is responsible for the backup, creation and
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   278
        final write of such file.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   279
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   280
        The `genid` argument is used to ensure the same set of file is only
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   281
        generated once. Call to `addfilegenerator` for a `genid` already
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   282
        present will overwrite the old entry.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   283
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   284
        The `order` argument may be used to control the order in which multiple
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   285
        generator will be executed.
23317
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   286
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   287
        The `location` arguments may be used to indicate the files are located
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   288
        outside of the the standard directory for transaction. It should match
23543
4dd8a6a1240d spelling: fixes from proofreading of spell checker issues
Mads Kiilerich <madski@unity3d.com>
parents: 23513
diff changeset
   289
        one of the key of the `transaction.vfsmap` dictionary.
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   290
        """
22663
4c6198737ad8 transaction: allow generating file outside of store
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22662
diff changeset
   291
        # For now, we are unable to do proper backup and restore of custom vfs
4c6198737ad8 transaction: allow generating file outside of store
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22662
diff changeset
   292
        # but for bookmarks that are handled outside this mechanism.
23317
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   293
        self._filegenerators[genid] = (order, filenames, genfunc, location)
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   294
29297
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
   295
    def _generatefiles(self, suffix='', group=gengroupall):
23102
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   296
        # write files registered for generation
23357
ba033f461f00 transaction: have _generatefile return a boolean
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23356
diff changeset
   297
        any = False
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   298
        for id, entry in sorted(self._filegenerators.iteritems()):
23357
ba033f461f00 transaction: have _generatefile return a boolean
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23356
diff changeset
   299
            any = True
23317
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   300
            order, filenames, genfunc, location = entry
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   301
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   302
            # for generation at closing, check if it's before or after finalize
29297
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
   303
            postfinalize = group == gengrouppostfinalize
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
   304
            if (group != gengroupall and
28830
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   305
                (id in postfinalizegenerators) != (postfinalize)):
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   306
                continue
a5009789960c transaction: allow running file generators after finalizers
Durham Goode <durham@fb.com>
parents: 27924
diff changeset
   307
23317
197e17be5407 transaction: use 'location' instead of 'vfs' objects for file generation
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23316
diff changeset
   308
            vfs = self._vfsmap[location]
23102
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   309
            files = []
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   310
            try:
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   311
                for name in filenames:
23356
140c21fbf4eb transaction: allow generating files with a suffix
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23355
diff changeset
   312
                    name += suffix
140c21fbf4eb transaction: allow generating files with a suffix
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23355
diff changeset
   313
                    if suffix:
140c21fbf4eb transaction: allow generating files with a suffix
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23355
diff changeset
   314
                        self.registertmp(name, location=location)
140c21fbf4eb transaction: allow generating files with a suffix
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23355
diff changeset
   315
                    else:
140c21fbf4eb transaction: allow generating files with a suffix
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23355
diff changeset
   316
                        self.addbackup(name, location=location)
29299
76b07a5c064b transaction: avoid ambiguity of file stat at closing transaction
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29297
diff changeset
   317
                    files.append(vfs(name, 'w', atomictemp=True,
76b07a5c064b transaction: avoid ambiguity of file stat at closing transaction
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29297
diff changeset
   318
                                     checkambig=not suffix))
23102
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   319
                genfunc(*files)
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   320
            finally:
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   321
                for f in files:
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   322
                    f.close()
23357
ba033f461f00 transaction: have _generatefile return a boolean
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23356
diff changeset
   323
        return any
23102
16da812ad970 transaction: extract file generation into its own function
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23065
diff changeset
   324
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   325
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   326
    def find(self, file):
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   327
        if file in self.map:
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   328
            return self.entries[self.map[file]]
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   329
        if file in self._backupmap:
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   330
            return self._backupentries[self._backupmap[file]]
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   331
        return None
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   332
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   333
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   334
    def replace(self, file, offset, data=None):
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   335
        '''
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   336
        replace can only replace already committed entries
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   337
        that are not pending in the queue
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   338
        '''
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   339
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   340
        if file not in self.map:
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   341
            raise KeyError(file)
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   342
        index = self.map[file]
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   343
        self.entries[index] = (file, offset, data)
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   344
        self.file.write("%s\0%d\n" % (file, offset))
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   345
        self.file.flush()
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   346
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   347
    @active
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   348
    def nest(self):
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   349
        self.count += 1
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   350
        self.usages += 1
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   351
        return self
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   352
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   353
    def release(self):
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   354
        if self.count > 0:
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   355
            self.usages -= 1
11685
aade8f133d11 cleanup: typos
Patrick Mezard <pmezard@gmail.com>
parents: 11230
diff changeset
   356
        # if the transaction scopes are left without being closed, fail
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   357
        if self.count > 0 and self.usages == 0:
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   358
            self._abort()
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   359
27862
b2145c195f24 transaction: turn a transaction into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 27662
diff changeset
   360
    def __enter__(self):
b2145c195f24 transaction: turn a transaction into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 27662
diff changeset
   361
        return self
b2145c195f24 transaction: turn a transaction into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 27662
diff changeset
   362
b2145c195f24 transaction: turn a transaction into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 27662
diff changeset
   363
    def __exit__(self, exc_type, exc_val, exc_tb):
27924
24361fb68cba transaction: abort transaction during hook exception
Durham Goode <durham@fb.com>
parents: 27862
diff changeset
   364
        try:
24361fb68cba transaction: abort transaction during hook exception
Durham Goode <durham@fb.com>
parents: 27862
diff changeset
   365
            if exc_type is None:
24361fb68cba transaction: abort transaction during hook exception
Durham Goode <durham@fb.com>
parents: 27862
diff changeset
   366
                self.close()
24361fb68cba transaction: abort transaction during hook exception
Durham Goode <durham@fb.com>
parents: 27862
diff changeset
   367
        finally:
24361fb68cba transaction: abort transaction during hook exception
Durham Goode <durham@fb.com>
parents: 27862
diff changeset
   368
            self.release()
27862
b2145c195f24 transaction: turn a transaction into a Python context manager
Bryan O'Sullivan <bryano@fb.com>
parents: 27662
diff changeset
   369
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   370
    def running(self):
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   371
        return self.count > 0
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   372
23202
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   373
    def addpending(self, category, callback):
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   374
        """add a callback to be called when the transaction is pending
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   375
23280
b01c491af0cf transaction: pass the transaction to 'pending' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23279
diff changeset
   376
        The transaction will be given as callback's first argument.
b01c491af0cf transaction: pass the transaction to 'pending' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23279
diff changeset
   377
23202
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   378
        Category is a unique identifier to allow overwriting an old callback
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   379
        with a newer callback.
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   380
        """
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   381
        self._pendingcallback[category] = callback
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   382
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   383
    @active
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   384
    def writepending(self):
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   385
        '''write pending file to temporary version
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   386
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   387
        This is used to allow hooks to view a transaction before commit'''
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   388
        categories = sorted(self._pendingcallback)
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   389
        for cat in categories:
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   390
            # remove callback since the data will have been flushed
23280
b01c491af0cf transaction: pass the transaction to 'pending' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23279
diff changeset
   391
            any = self._pendingcallback.pop(cat)(self)
23202
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   392
            self._anypending = self._anypending or any
23358
1b51d1b05482 transaction: write pending generated files
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23357
diff changeset
   393
        self._anypending |= self._generatefiles(suffix='.pending')
23202
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   394
        return self._anypending
ea5af863fbff transaction: add 'writepending' logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23103
diff changeset
   395
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   396
    @active
23204
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   397
    def addfinalize(self, category, callback):
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   398
        """add a callback to be called when the transaction is closed
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   399
23281
f60ed8cf4afc transaction: pass the transaction to 'finalize' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23280
diff changeset
   400
        The transaction will be given as callback's first argument.
f60ed8cf4afc transaction: pass the transaction to 'finalize' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23280
diff changeset
   401
23204
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   402
        Category is a unique identifier to allow overwriting old callbacks with
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   403
        newer callbacks.
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   404
        """
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   405
        self._finalizecallback[category] = callback
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   406
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   407
    @active
23220
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   408
    def addpostclose(self, category, callback):
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   409
        """add a callback to be called after the transaction is closed
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   410
23282
6c1351352b6c transaction: pass the transaction to 'postclose' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23281
diff changeset
   411
        The transaction will be given as callback's first argument.
6c1351352b6c transaction: pass the transaction to 'postclose' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23281
diff changeset
   412
23220
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   413
        Category is a unique identifier to allow overwriting an old callback
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   414
        with a newer callback.
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   415
        """
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   416
        self._postclosecallback[category] = callback
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   417
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   418
    @active
23764
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   419
    def addabort(self, category, callback):
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   420
        """add a callback to be called when the transaction is aborted.
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   421
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   422
        The transaction will be given as the first argument to the callback.
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   423
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   424
        Category is a unique identifier to allow overwriting an old callback
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   425
        with a newer callback.
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   426
        """
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   427
        self._abortcallback[category] = callback
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   428
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   429
    @active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   430
    def close(self):
9220
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   431
        '''commit the transaction'''
23290
59513ec76748 transaction: always generate file on close
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23283
diff changeset
   432
        if self.count == 1:
24283
ef22cfff7052 transaction: add a validation stage
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23904
diff changeset
   433
            self.validator(self)  # will raise exception if needed
32558
aa91085cadf3 transaction: delete callbacks after use
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   434
            self.validator = None # Help prevent cycles.
29297
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
   435
            self._generatefiles(group=gengroupprefinalize)
23204
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   436
            categories = sorted(self._finalizecallback)
10beda5bd2b7 transaction: allow registering a finalization callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23202
diff changeset
   437
            for cat in categories:
23281
f60ed8cf4afc transaction: pass the transaction to 'finalize' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23280
diff changeset
   438
                self._finalizecallback[cat](self)
28960
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   439
            # Prevent double usage and help clear cycles.
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   440
            self._finalizecallback = None
29297
50fef8252820 style: remove namespace class
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 29296
diff changeset
   441
            self._generatefiles(group=gengrouppostfinalize)
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   442
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   443
        self.count -= 1
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   444
        if self.count != 0:
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   445
            return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   446
        self.file.close()
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   447
        self._backupsfile.close()
23291
03d2d6931836 transaction: allow registering a temporary transaction file
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23290
diff changeset
   448
        # cleanup temporary files
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   449
        for l, f, b, c in self._backupentries:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   450
            if l not in self._vfsmap and c:
26754
e7e1528cf200 spelling: fix typo in transaction error messages
Matt Mackall <mpm@selenic.com>
parents: 26753
diff changeset
   451
                self.report("couldn't remove %s: unknown cache location %s\n"
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   452
                            % (b, l))
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   453
                continue
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   454
            vfs = self._vfsmap[l]
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   455
            if not f and b and vfs.exists(b):
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   456
                try:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   457
                    vfs.unlink(b)
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26576
diff changeset
   458
                except (IOError, OSError, error.Abort) as inst:
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   459
                    if not c:
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   460
                        raise
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   461
                    # Abort may be raise by read only opener
26754
e7e1528cf200 spelling: fix typo in transaction error messages
Matt Mackall <mpm@selenic.com>
parents: 26753
diff changeset
   462
                    self.report("couldn't remove %s: %s\n"
23312
006e9ef05c31 transaction: support cache file in backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23311
diff changeset
   463
                                % (vfs.join(b), inst))
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   464
        self.entries = []
23904
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   465
        self._writeundo()
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
   466
        if self.after:
785
46a8dd3145cc Fix undo after aborted commit bug
mpm@selenic.com
parents: 582
diff changeset
   467
            self.after()
32558
aa91085cadf3 transaction: delete callbacks after use
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   468
            self.after = None # Help prevent cycles.
26753
96dd93de548c transaction: reorder unlinking .hg/journal and .hg/journal.backupfiles
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26587
diff changeset
   469
        if self.opener.isfile(self._backupjournal):
96dd93de548c transaction: reorder unlinking .hg/journal and .hg/journal.backupfiles
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26587
diff changeset
   470
            self.opener.unlink(self._backupjournal)
20087
cf3b8285af00 transaction: take journal file path relative to vfs to use file API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20084
diff changeset
   471
        if self.opener.isfile(self.journal):
cf3b8285af00 transaction: take journal file path relative to vfs to use file API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20084
diff changeset
   472
            self.opener.unlink(self.journal)
27662
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   473
        for l, _f, b, c in self._backupentries:
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   474
            if l not in self._vfsmap and c:
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   475
                self.report("couldn't remove %s: unknown cache location"
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   476
                            "%s\n" % (b, l))
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   477
                continue
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   478
            vfs = self._vfsmap[l]
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   479
            if b and vfs.exists(b):
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   480
                try:
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   481
                    vfs.unlink(b)
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   482
                except (IOError, OSError, error.Abort) as inst:
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   483
                    if not c:
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   484
                        raise
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   485
                    # Abort may be raise by read only opener
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   486
                    self.report("couldn't remove %s: %s\n"
f7ab50c721ac transaction: remove 'if True:'
Martin von Zweigbergk <martinvonz@google.com>
parents: 26754
diff changeset
   487
                                % (vfs.join(b), inst))
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   488
        self._backupentries = []
573
fbfbd4e506c3 transaction: nullify journal after close()
mpm@selenic.com
parents: 558
diff changeset
   489
        self.journal = None
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   490
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   491
        self.releasefn(self, True) # notify success of closing transaction
32558
aa91085cadf3 transaction: delete callbacks after use
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   492
        self.releasefn = None # Help prevent cycles.
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   493
23220
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   494
        # run post close action
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   495
        categories = sorted(self._postclosecallback)
3f543f6be500 transaction: allow registering a post-close callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23204
diff changeset
   496
        for cat in categories:
23282
6c1351352b6c transaction: pass the transaction to 'postclose' callback
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23281
diff changeset
   497
            self._postclosecallback[cat](self)
28960
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   498
        # Prevent double usage and help clear cycles.
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   499
        self._postclosecallback = None
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   500
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   501
    @active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   502
    def abort(self):
9220
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   503
        '''abort the transaction (generally called on error, or when the
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   504
        transaction is not explicitly committed before going out of
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   505
        scope)'''
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   506
        self._abort()
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   507
23904
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   508
    def _writeundo(self):
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   509
        """write transaction data for possible future undo call"""
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   510
        if self.undoname is None:
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   511
            return
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   512
        undobackupfile = self.opener.open("%s.backupfiles" % self.undoname, 'w')
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   513
        undobackupfile.write('%d\n' % version)
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   514
        for l, f, b, c in self._backupentries:
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   515
            if not f:  # temporary file
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   516
                continue
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   517
            if not b:
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   518
                u = ''
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   519
            else:
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   520
                if l not in self._vfsmap and c:
26754
e7e1528cf200 spelling: fix typo in transaction error messages
Matt Mackall <mpm@selenic.com>
parents: 26753
diff changeset
   521
                    self.report("couldn't remove %s: unknown cache location"
23904
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   522
                                "%s\n" % (b, l))
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   523
                    continue
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   524
                vfs = self._vfsmap[l]
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   525
                base, name = vfs.split(b)
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   526
                assert name.startswith(self.journal), name
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   527
                uname = name.replace(self.journal, self.undoname, 1)
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   528
                u = vfs.reljoin(base, uname)
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   529
                util.copyfile(vfs.join(b), vfs.join(u), hardlink=True)
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   530
            undobackupfile.write("%s\0%s\0%s\0%d\n" % (l, f, u, c))
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   531
        undobackupfile.close()
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   532
d251da5e0e84 transaction: include backup file in the "undo" transaction
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23903
diff changeset
   533
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   534
    def _abort(self):
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   535
        self.count = 0
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   536
        self.usages = 0
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   537
        self.file.close()
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   538
        self._backupsfile.close()
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   539
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   540
        try:
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   541
            if not self.entries and not self._backupentries:
26753
96dd93de548c transaction: reorder unlinking .hg/journal and .hg/journal.backupfiles
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26587
diff changeset
   542
                if self._backupjournal:
96dd93de548c transaction: reorder unlinking .hg/journal and .hg/journal.backupfiles
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 26587
diff changeset
   543
                    self.opener.unlink(self._backupjournal)
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   544
                if self.journal:
20087
cf3b8285af00 transaction: take journal file path relative to vfs to use file API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20084
diff changeset
   545
                    self.opener.unlink(self.journal)
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   546
                return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   547
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   548
            self.report(_("transaction abort!\n"))
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   549
108
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
   550
            try:
23764
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   551
                for cat in sorted(self._abortcallback):
d486e52352e8 transaction: support for callbacks during abort
Gregory Szorc <gregory.szorc@gmail.com>
parents: 23727
diff changeset
   552
                    self._abortcallback[cat](self)
28960
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   553
                # Prevent double usage and help clear cycles.
14e683d6b273 transaction: clear callback instances after usage
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28830
diff changeset
   554
                self._abortcallback = None
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   555
                _playback(self.journal, self.report, self.opener, self._vfsmap,
23249
84720eab4fbd transaction: mark backup-related attributes private
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23248
diff changeset
   556
                          self.entries, self._backupentries, False)
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   557
                self.report(_("rollback completed\n"))
25183
0d0ed375fbdf recover: catch any exception, not just Exception
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24721
diff changeset
   558
            except BaseException:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   559
                self.report(_("rollback failed - please run hg recover\n"))
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   560
        finally:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   561
            self.journal = None
26576
9e0aaac0d9eb transaction: add releasefn to notify the end of a transaction scope
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 25986
diff changeset
   562
            self.releasefn(self, False) # notify failure of transaction
32558
aa91085cadf3 transaction: delete callbacks after use
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32291
diff changeset
   563
            self.releasefn = None # Help prevent cycles.
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   564
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   565
def rollback(opener, vfsmap, file, report):
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   566
    """Rolls back the transaction contained in the given file
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   567
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   568
    Reads the entries in the specified file, and the corresponding
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   569
    '*.backupfiles' file, to recover from an incomplete transaction.
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   570
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   571
    * `file`: a file containing a list of entries, specifying where
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   572
    to truncate each file.  The file should contain a list of
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   573
    file\0offset pairs, delimited by newlines. The corresponding
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   574
    '*.backupfiles' file should contain a list of file\0backupfile
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   575
    pairs, delimited by \0.
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   576
    """
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   577
    entries = []
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   578
    backupentries = []
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   579
20087
cf3b8285af00 transaction: take journal file path relative to vfs to use file API via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20084
diff changeset
   580
    fp = opener.open(file)
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   581
    lines = fp.readlines()
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   582
    fp.close()
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   583
    for l in lines:
20524
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   584
        try:
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   585
            f, o = l.split('\0')
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   586
            entries.append((f, int(o), None))
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   587
        except ValueError:
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   588
            report(_("couldn't read journal entry %r!\n") % l)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   589
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   590
    backupjournal = "%s.backupfiles" % file
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   591
    if opener.exists(backupjournal):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   592
        fp = opener.open(backupjournal)
23065
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   593
        lines = fp.readlines()
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   594
        if lines:
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   595
            ver = lines[0][:-1]
23064
5dc888b79e70 transactions: add version number to journal.backupfiles
Durham Goode <durham@fb.com>
parents: 23063
diff changeset
   596
            if ver == str(version):
23065
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   597
                for line in lines[1:]:
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   598
                    if line:
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   599
                        # Shave off the trailing newline
963f311e3a81 transactions: change backupfiles format to use newlines
Durham Goode <durham@fb.com>
parents: 23064
diff changeset
   600
                        line = line[:-1]
23309
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
   601
                        l, f, b, c = line.split('\0')
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
   602
                        backupentries.append((l, f, b, bool(c)))
23064
5dc888b79e70 transactions: add version number to journal.backupfiles
Durham Goode <durham@fb.com>
parents: 23063
diff changeset
   603
            else:
23309
7eb520f5efe4 transaction: change the on disk format for backupentries
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23291
diff changeset
   604
                report(_("journal was created by a different version of "
24721
774ee9800146 transaction: add missing newline to message
Michael O'Connor <moconnor@janestreet.com>
parents: 24283
diff changeset
   605
                         "Mercurial\n"))
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   606
23311
64ab33ffba14 transaction: use the location value when doing backup
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23310
diff changeset
   607
    _playback(file, report, opener, vfsmap, entries, backupentries)