mercurial/transaction.py
author Pierre-Yves David <pierre-yves.david@fb.com>
Thu, 07 Aug 2014 14:40:02 -0700
changeset 22078 feb4797c676e
parent 22077 2990ce46fc2d
child 22199 b3e51675f98e
permissions -rw-r--r--
transaction: add a file generation mechanism A new `transaction.addfilegenerator` function is added. It allows external code to register files to be generated. See inline documentation for details. It is important to gather all file creation logic on the transaction as at some point we'll want to mimic the "pre-transaction-commit" logic that we use for revlog. I'm refering to the logic that lets hooks see the result of the transaction before it actually gets committed.
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
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
    14
from i18n import _
20886
203908968644 transaction: drop extra import caught by pyflakes
Matt Mackall <mpm@selenic.com>
parents: 20882
diff changeset
    15
import errno
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    16
import error, util
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    17
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    18
def active(func):
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    19
    def _active(self, *args, **kwds):
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    20
        if self.count == 0:
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    21
            raise error.Abort(_(
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    22
                '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
    23
        return func(self, *args, **kwds)
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
    24
    return _active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    25
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    26
def _playback(journal, report, opener, entries, backupentries, unlink=True):
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    27
    for f, o, ignore in entries:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    28
        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
    29
            try:
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
    30
                fp = opener(f, 'a')
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
    31
                fp.truncate(o)
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
    32
                fp.close()
9686
ddf2adf88b89 transaction: more specific exceptions, os.unlink can raise OSError
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9220
diff changeset
    33
            except IOError:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    34
                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
    35
                raise
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    36
        else:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    37
            try:
20084
a3378a1b0a05 transaction: unlink target file via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17424
diff changeset
    38
                opener.unlink(f)
9686
ddf2adf88b89 transaction: more specific exceptions, os.unlink can raise OSError
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9220
diff changeset
    39
            except (IOError, OSError), inst:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    40
                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
    41
                    raise
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    42
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    43
    backupfiles = []
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    44
    for f, b, ignore in backupentries:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    45
        filepath = opener.join(f)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    46
        backuppath = opener.join(b)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    47
        try:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    48
            util.copyfile(backuppath, filepath)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    49
            backupfiles.append(b)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    50
        except IOError:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    51
            report(_("failed to recover %s\n") % f)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    52
            raise
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    53
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
    54
    opener.unlink(journal)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    55
    backuppath = "%s.backupfiles" % journal
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    56
    if opener.exists(backuppath):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    57
        opener.unlink(backuppath)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    58
    for f in backupfiles:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    59
        opener.unlink(f)
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
    60
1559
59b3639df0a9 Convert all classes to new-style classes by deriving them from object.
Eric Hopper <hopper@omnifarious.org>
parents: 1541
diff changeset
    61
class transaction(object):
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    62
    def __init__(self, report, opener, journal, after=None, createmode=None,
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    63
            onclose=None, onabort=None):
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    64
        """Begin a new transaction
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    65
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    66
        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
    67
        an exception.
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    68
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    69
        * `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
    70
        * `createmode`: the mode of the journal file that will be created
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    71
        * `onclose`: called as the transaction is closing, but before it is
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    72
        closed
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    73
        * `onabort`: called as the transaction is aborting, but before any files
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    74
        have been truncated
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    75
        """
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
    76
        self.count = 1
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
    77
        self.usages = 1
582
df8a5a0098d4 Remove all remaining print statements
mpm@selenic.com
parents: 573
diff changeset
    78
        self.report = report
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    79
        self.opener = opener
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
    80
        self.after = after
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    81
        self.onclose = onclose
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
    82
        self.onabort = onabort
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    83
        self.entries = []
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    84
        self.backupentries = []
42
91f1fa847158 Fix multiple changes to file per transaction
mpm@selenic.com
parents: 13
diff changeset
    85
        self.map = {}
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    86
        self.backupmap = {}
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    87
        self.journal = journal
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
    88
        self._queue = []
21150
0d05915b688d transaction: add a notion of hook arguments
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20886
diff changeset
    89
        # a dict of arguments to be passed to hooks
0d05915b688d transaction: add a notion of hook arguments
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20886
diff changeset
    90
        self.hookargs = {}
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    91
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    92
        self.backupjournal = "%s.backupfiles" % 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
    93
        self.file = opener.open(self.journal, "w")
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    94
        self.backupsfile = opener.open(self.backupjournal, 'w')
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
    95
        if createmode is not None:
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
    96
            opener.chmod(self.journal, createmode & 0666)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
    97
            opener.chmod(self.backupjournal, createmode & 0666)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    98
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
    99
        # 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
   100
        self._filegenerators = {}
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   101
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   102
    def __del__(self):
558
0ceea19182a9 transaction: __del__ should do nothing if the journal already exists
mpm@selenic.com
parents: 515
diff changeset
   103
        if self.journal:
9693
c40a1ee20aa5 transaction: always remove empty journal on abort
Sune Foldager <cryo@cyanite.org>
parents: 9686
diff changeset
   104
            self._abort()
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   105
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   106
    @active
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   107
    def startgroup(self):
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   108
        self._queue.append(([], []))
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   109
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   110
    @active
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   111
    def endgroup(self):
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   112
        q = self._queue.pop()
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   113
        self.entries.extend(q[0])
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   114
        self.backupentries.extend(q[1])
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   115
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   116
        offsets = []
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   117
        backups = []
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   118
        for f, o, _ in q[0]:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   119
            offsets.append((f, o))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   120
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   121
        for f, b, _ in q[1]:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   122
            backups.append((f, b))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   123
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   124
        d = ''.join(['%s\0%d\n' % (f, o) for f, o in offsets])
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   125
        self.file.write(d)
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   126
        self.file.flush()
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   127
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   128
        d = ''.join(['%s\0%s\0' % (f, b) for f, b in backups])
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   129
        self.backupsfile.write(d)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   130
        self.backupsfile.flush()
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   131
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   132
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   133
    def add(self, file, offset, data=None):
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   134
        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
   135
            return
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   136
        if self._queue:
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   137
            self._queue[-1][0].append((file, offset, data))
8363
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   138
            return
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   139
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   140
        self.entries.append((file, offset, data))
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   141
        self.map[file] = len(self.entries) - 1
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   142
        # 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
   143
        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
   144
        self.file.flush()
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   145
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   146
    @active
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   147
    def addbackup(self, file, hardlink=True):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   148
        """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
   149
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   150
        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
   151
        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
   152
        aborting.
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   153
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   154
        * `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
   155
        * `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
   156
        """
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   157
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   158
        if file in self.map or file in self.backupmap:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   159
            return
22077
2990ce46fc2d transaction: backup file in a dedicated "namespace"
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22076
diff changeset
   160
        backupfile = "%s.backup.%s" % (self.journal, file)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   161
        if self.opener.exists(file):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   162
            filepath = self.opener.join(file)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   163
            backuppath = self.opener.join(backupfile)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   164
            util.copyfiles(filepath, backuppath, hardlink=hardlink)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   165
        else:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   166
            self.add(file, 0)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   167
            return
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   168
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   169
        if self._queue:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   170
            self._queue[-1][1].append((file, backupfile))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   171
            return
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   172
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   173
        self.backupentries.append((file, backupfile, None))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   174
        self.backupmap[file] = len(self.backupentries) - 1
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   175
        self.backupsfile.write("%s\0%s\0" % (file, backupfile))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   176
        self.backupsfile.flush()
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   177
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   178
    @active
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   179
    def addfilegenerator(self, genid, filenames, genfunc, order=0):
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   180
        """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
   181
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   182
        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
   183
        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
   184
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   185
        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
   186
        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
   187
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   188
        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
   189
        final write of such file.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   190
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   191
        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
   192
        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
   193
        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
   194
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   195
        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
   196
        generator will be executed.
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   197
        """
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   198
        self._filegenerators[genid] = (order, filenames, genfunc)
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   199
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   200
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   201
    def find(self, file):
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   202
        if file in self.map:
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   203
            return self.entries[self.map[file]]
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   204
        if file in self.backupmap:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   205
            return self.backupentries[self.backupmap[file]]
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   206
        return None
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   207
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   208
    @active
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   209
    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
   210
        '''
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   211
        replace can only replace already committed entries
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   212
        that are not pending in the queue
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   213
        '''
c8e81f557da7 transaction: add atomic groups to transaction logic
Henrik Stuart <hg@hstuart.dk>
parents: 8294
diff changeset
   214
2084
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   215
        if file not in self.map:
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   216
            raise KeyError(file)
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   217
        index = self.map[file]
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   218
        self.entries[index] = (file, offset, data)
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   219
        self.file.write("%s\0%d\n" % (file, offset))
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   220
        self.file.flush()
Chris Mason <mason@suse.com>
parents: 1806
diff changeset
   221
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   222
    @active
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   223
    def nest(self):
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   224
        self.count += 1
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   225
        self.usages += 1
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   226
        return self
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   227
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   228
    def release(self):
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   229
        if self.count > 0:
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   230
            self.usages -= 1
11685
aade8f133d11 cleanup: typos
Patrick Mezard <pmezard@gmail.com>
parents: 11230
diff changeset
   231
        # 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
   232
        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
   233
            self._abort()
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   234
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   235
    def running(self):
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   236
        return self.count > 0
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   237
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   238
    @active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   239
    def close(self):
9220
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   240
        '''commit the transaction'''
22078
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   241
        # write files registered for generation
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   242
        for order, filenames, genfunc in sorted(self._filegenerators.values()):
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   243
            files = []
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   244
            try:
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   245
                for name in filenames:
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   246
                    self.addbackup(name)
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   247
                    files.append(self.opener(name, 'w', atomictemp=True))
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   248
                genfunc(*files)
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   249
            finally:
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   250
                for f in files:
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   251
                    f.close()
feb4797c676e transaction: add a file generation mechanism
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22077
diff changeset
   252
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   253
        if self.count == 1 and self.onclose is not None:
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   254
            self.onclose()
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   255
1806
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   256
        self.count -= 1
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   257
        if self.count != 0:
a2c69737e65e Automatic nesting into running transactions in the same repository.
mason@suse.com
parents: 1559
diff changeset
   258
            return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   259
        self.file.close()
21206
c77418938d05 transaction: fix file descriptor leak for journal.backupfiles
Durham Goode <durham@fb.com>
parents: 21150
diff changeset
   260
        self.backupsfile.close()
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   261
        self.entries = []
95
589f507bb259 Beginnings of transaction undo support
mpm@selenic.com
parents: 43
diff changeset
   262
        if self.after:
785
46a8dd3145cc Fix undo after aborted commit bug
mpm@selenic.com
parents: 582
diff changeset
   263
            self.after()
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
   264
        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
   265
            self.opener.unlink(self.journal)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   266
        if self.opener.isfile(self.backupjournal):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   267
            self.opener.unlink(self.backupjournal)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   268
            for f, b, _ in self.backupentries:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   269
                self.opener.unlink(b)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   270
        self.backupentries = []
573
fbfbd4e506c3 transaction: nullify journal after close()
mpm@selenic.com
parents: 558
diff changeset
   271
        self.journal = None
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   272
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   273
    @active
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   274
    def abort(self):
9220
8a4da1388553 transaction: document close(), abort() methods
Greg Ward <greg-hg@gerg.ca>
parents: 9094
diff changeset
   275
        '''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
   276
        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
   277
        scope)'''
8289
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   278
        self._abort()
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   279
fe8a3e56039f transaction: ensure finished transactions are not reused
Henrik Stuart <hg@hstuart.dk>
parents: 8225
diff changeset
   280
    def _abort(self):
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   281
        self.count = 0
11230
5116a077c3da make transactions work on non-refcounted python implementations
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents: 10282
diff changeset
   282
        self.usages = 0
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   283
        self.file.close()
21206
c77418938d05 transaction: fix file descriptor leak for journal.backupfiles
Durham Goode <durham@fb.com>
parents: 21150
diff changeset
   284
        self.backupsfile.close()
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   285
20881
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   286
        if self.onabort is not None:
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   287
            self.onabort()
3c47677a8d04 transaction: add onclose/onabort hook for pre-close logic
Durham Goode <durham@fb.com>
parents: 20524
diff changeset
   288
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   289
        try:
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   290
            if not self.entries and not self.backupentries:
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   291
                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
   292
                    self.opener.unlink(self.journal)
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   293
                if self.backupjournal:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   294
                    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
   295
                return
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   296
10228
056c366fea8c transaction: initialize self.journal to None after deletion
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9693
diff changeset
   297
            self.report(_("transaction abort!\n"))
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   298
108
8d55c2d72c7c Warn if we fail to truncate something
mpm@selenic.com
parents: 95
diff changeset
   299
            try:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
   300
                _playback(self.journal, self.report, self.opener,
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   301
                          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
   302
                self.report(_("rollback completed\n"))
16689
f366d4c2ff34 cleanup: replace naked excepts with except Exception: ...
Brodie Rao <brodie@sf.io>
parents: 13408
diff changeset
   303
            except Exception:
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   304
                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
   305
        finally:
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   306
            self.journal = None
8290
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   307
560af1bbfd6e transaction: reset transaction on abort
Henrik Stuart <hg@hstuart.dk>
parents: 8289
diff changeset
   308
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   309
def rollback(opener, file, report):
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   310
    """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
   311
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   312
    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
   313
    '*.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
   314
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   315
    * `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
   316
    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
   317
    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
   318
    '*.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
   319
    pairs, delimited by \0.
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   320
    """
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   321
    entries = []
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   322
    backupentries = []
8294
48a382c23226 transaction: refactor transaction.abort and rollback to use the same code
Henrik Stuart <hg@hstuart.dk>
parents: 8290
diff changeset
   323
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
   324
    fp = opener.open(file)
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   325
    lines = fp.readlines()
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   326
    fp.close()
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 11685
diff changeset
   327
    for l in lines:
20524
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   328
        try:
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   329
            f, o = l.split('\0')
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   330
            entries.append((f, int(o), None))
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   331
        except ValueError:
28b8ff84db3f journal: report parsing errors on recover/rollback (issue4172)
Matt Mackall <mpm@selenic.com>
parents: 20087
diff changeset
   332
            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
   333
20882
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   334
    backupjournal = "%s.backupfiles" % file
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   335
    if opener.exists(backupjournal):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   336
        fp = opener.open(backupjournal)
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   337
        data = fp.read()
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   338
        if len(data) > 0:
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   339
            parts = data.split('\0')
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   340
            for i in xrange(0, len(parts), 2):
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   341
                f, b = parts[i:i + 1]
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   342
                backupentries.append((f, b, None))
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   343
5dffd06f1e50 transaction: add support for non-append files
Durham Goode <durham@fb.com>
parents: 20881
diff changeset
   344
    _playback(file, report, opener, entries, backupentries)