mercurial/repair.py
author Gregory Szorc <gregory.szorc@gmail.com>
Tue, 20 Feb 2018 18:55:58 -0800
branchstable
changeset 36755 ff4bc0ab6740
parent 35778 128dd940bedc
child 36702 f659a407e5ee
permissions -rw-r--r--
wireproto: check permissions when executing "batch" command (BC) (SEC) For as long as the "batch" command has existed (introduced by bd88561afb4b and first released as part of Mercurial 1.9), that command (like most wire commands introduced after 2008) lacked an entry in the hgweb permissions table. And since we don't verify permissions if an entry is missing from the permissions table, this meant that executing a command via "batch" would bypass all permissions checks. The security implications are significant: a Mercurial HTTP server would allow writes via "batch" wire protocol commands as long as the HTTP request were processed by Mercurial and the process running the Mercurial HTTP server had write access to the repository. The Mercurial defaults of servers being read-only and the various web.* config options to define access control were bypassed. In addition, "batch" could be used to exfiltrate data from servers that were configured to not allow read access. Both forms of permissions bypass could be mitigated to some extent by using HTTP authentication. This would prevent HTTP requests from hitting Mercurial's server logic. However, any authenticated request would still be able to bypass permissions checks via "batch" commands. The easiest exploit was to send "pushkey" commands via "batch" and modify the state of bookmarks, phases, and obsolescence markers. However, I suspect a well-crafted HTTP request could trick the server into running the "unbundle" wire protocol command, effectively performing a full `hg push` to create new changesets on the remote. This commit plugs this gaping security hole by having the "batch" command perform permissions checking on each sub-command that is being batched. We do this by threading a permissions checking callable all the way to the protocol handler. The threading is a bit hacky from a code perspective. But it preserves API compatibility, which is the proper thing to do on the stable branch. One of the subtle things we do is assume that a command with an undefined permission is a "push" command. This is the safest thing to do from a security perspective: we don't want to take chances that a command could perform a write even though the server is configured to not allow writes. As the test changes demonstrate, it is no longer possible to bypass permissions via the "batch" wire protocol command. .. bc:: The "batch" wire protocol command now enforces permissions of each invoked sub-command. Wire protocol commands must define their operation type or the "batch" command will assume they can write data and will prevent their execution on HTTP servers unless the HTTP request method is POST, the server is configured to allow pushes, and the (possibly authenticated) HTTP user is authorized to perform a push.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# repair.py - functions for repository repair for mercurial
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# Copyright 2005, 2006 Chris Mason <mason@suse.com>
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
# Copyright 2007 Matt Mackall
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8073
diff changeset
     6
# 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: 9150
diff changeset
     7
# GNU General Public License version 2 or any later version.
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
25970
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
     9
from __future__ import absolute_import
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    10
16440
692bf06bb1af repair: fix missing import
Alain Leufroy <alain.leufroy@logilab.fr>
parents: 16388
diff changeset
    11
import errno
29341
0d83ad967bf8 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
Augie Fackler <raf@durin42.com>
parents: 29196
diff changeset
    12
import hashlib
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
25970
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    14
from .i18n import _
34222
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    15
from .node import (
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    16
    hex,
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    17
    short,
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    18
)
25970
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    19
from . import (
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    20
    bundle2,
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    21
    changegroup,
32468
4c4d91908492 strip: use the 'writenewbundle' function to get bundle on disk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32296
diff changeset
    22
    discovery,
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26425
diff changeset
    23
    error,
25970
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    24
    exchange,
28868
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
    25
    obsolete,
33143
d09ae850296d obsutil: move 'exclusivemarkers' to the new modules
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 33108
diff changeset
    26
    obsutil,
25970
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    27
    util,
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    28
)
d1419cfbd4f4 repair: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25874
diff changeset
    29
32628
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
    30
def _bundle(repo, bases, heads, node, suffix, compress=True, obsolescence=True):
5905
3afbd82a6c82 repair.py: don't use nested functions.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5904
diff changeset
    31
    """create a bundle with the specified revisions as a backup"""
23898
b21c2e0ee8a3 repair: add experimental option to write bundle2 files
Eric Sumner <ericsumner@fb.com>
parents: 23895
diff changeset
    32
20977
a57dcd11be34 repair: make paths in "_bundle()" relative to ".hg"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20975
diff changeset
    33
    backupdir = "strip-backup"
a57dcd11be34 repair: make paths in "_bundle()" relative to ".hg"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20975
diff changeset
    34
    vfs = repo.vfs
a57dcd11be34 repair: make paths in "_bundle()" relative to ".hg"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20975
diff changeset
    35
    if not vfs.isdir(backupdir):
a57dcd11be34 repair: make paths in "_bundle()" relative to ".hg"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20975
diff changeset
    36
        vfs.mkdir(backupdir)
23835
aa4a1672583e bundles: do not overwrite existing backup bundles (BC)
Durham Goode <durham@fb.com>
parents: 22818
diff changeset
    37
aa4a1672583e bundles: do not overwrite existing backup bundles (BC)
Durham Goode <durham@fb.com>
parents: 22818
diff changeset
    38
    # Include a hash of all the nodes in the filename for uniqueness
25340
28800ab40395 repair: use _hexlist() to build revset expression from binary nodes
Yuya Nishihara <yuya@tcha.org>
parents: 25300
diff changeset
    39
    allcommits = repo.set('%ln::%ln', bases, heads)
23835
aa4a1672583e bundles: do not overwrite existing backup bundles (BC)
Durham Goode <durham@fb.com>
parents: 22818
diff changeset
    40
    allhashes = sorted(c.hex() for c in allcommits)
34222
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    41
    totalhash = hashlib.sha1(''.join(allhashes)).digest()
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    42
    name = "%s/%s-%s-%s.hg" % (backupdir, short(node),
6193d810f7bb repair: reliably obtain bytestr of node ids
Augie Fackler <raf@durin42.com>
parents: 33725
diff changeset
    43
                               hex(totalhash[:4]), suffix)
23835
aa4a1672583e bundles: do not overwrite existing backup bundles (BC)
Durham Goode <durham@fb.com>
parents: 22818
diff changeset
    44
34144
91f0677dc920 repair: preserve phase also when not using generaldelta (issue5678)
Martin von Zweigbergk <martinvonz@google.com>
parents: 33490
diff changeset
    45
    cgversion = changegroup.localversion(repo)
26425
eb21b6679dc6 strip: compress bundle2 backup using BZ
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26423
diff changeset
    46
    comp = None
26423
c93f91c1db1c strip: use bundle2 + cg2 by default when repository use general delta
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26014
diff changeset
    47
    if cgversion != '01':
24686
e0e28e910fa3 bundle2: rename format, parts and config to final names
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 24252
diff changeset
    48
        bundletype = "HG20"
26425
eb21b6679dc6 strip: compress bundle2 backup using BZ
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26423
diff changeset
    49
        if compress:
eb21b6679dc6 strip: compress bundle2 backup using BZ
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26423
diff changeset
    50
            comp = 'BZ'
23898
b21c2e0ee8a3 repair: add experimental option to write bundle2 files
Eric Sumner <ericsumner@fb.com>
parents: 23895
diff changeset
    51
    elif compress:
11791
00cde9bddbe4 repair: do not compress partial bundle if we do not keep it on disk
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11600
diff changeset
    52
        bundletype = "HG10BZ"
00cde9bddbe4 repair: do not compress partial bundle if we do not keep it on disk
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11600
diff changeset
    53
    else:
00cde9bddbe4 repair: do not compress partial bundle if we do not keep it on disk
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents: 11600
diff changeset
    54
        bundletype = "HG10UN"
32468
4c4d91908492 strip: use the 'writenewbundle' function to get bundle on disk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32296
diff changeset
    55
4c4d91908492 strip: use the 'writenewbundle' function to get bundle on disk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32296
diff changeset
    56
    outgoing = discovery.outgoing(repo, missingroots=bases, missingheads=heads)
33032
8e3021fd1a44 strip: include phases in bundle (BC)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32930
diff changeset
    57
    contentopts = {
8e3021fd1a44 strip: include phases in bundle (BC)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32930
diff changeset
    58
        'cg.version': cgversion,
8e3021fd1a44 strip: include phases in bundle (BC)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32930
diff changeset
    59
        'obsolescence': obsolescence,
8e3021fd1a44 strip: include phases in bundle (BC)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32930
diff changeset
    60
        'phases': True,
8e3021fd1a44 strip: include phases in bundle (BC)
Martin von Zweigbergk <martinvonz@google.com>
parents: 32930
diff changeset
    61
    }
32468
4c4d91908492 strip: use the 'writenewbundle' function to get bundle on disk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32296
diff changeset
    62
    return bundle2.writenewbundle(repo.ui, repo, 'strip', name, bundletype,
4c4d91908492 strip: use the 'writenewbundle' function to get bundle on disk
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32296
diff changeset
    63
                                  outgoing, contentopts, vfs, compression=comp)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
5910
b9a830fa10f6 simplify revlog.strip interface and callers; add docstring
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5909
diff changeset
    65
def _collectfiles(repo, striprev):
b9a830fa10f6 simplify revlog.strip interface and callers; add docstring
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5909
diff changeset
    66
    """find out the filelogs affected by the strip"""
8462
e7e4e41b3bbc repair: use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8363
diff changeset
    67
    files = set()
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
6750
fb42030d79d6 add __len__ and __iter__ methods to repo and revlog
Matt Mackall <mpm@selenic.com>
parents: 6747
diff changeset
    69
    for x in xrange(striprev, len(repo)):
8479
3e16c0fc2241 repair: bulk update sets
Martin Geisler <mg@lazybytes.net>
parents: 8462
diff changeset
    70
        files.update(repo[x].files())
5902
98f8dec8f437 repair.py: split stripall into two functions; clean it up a bit
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5901
diff changeset
    71
8462
e7e4e41b3bbc repair: use set instead of dict
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8363
diff changeset
    72
    return sorted(files)
5902
98f8dec8f437 repair.py: split stripall into two functions; clean it up a bit
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5901
diff changeset
    73
33724
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    74
def _collectrevlog(revlog, striprev):
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    75
    _, brokenset = revlog.getstrippoint(striprev)
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    76
    return [revlog.linkrev(r) for r in brokenset]
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    77
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    78
def _collectmanifest(repo, striprev):
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    79
    return _collectrevlog(repo.manifestlog._revlog, striprev)
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    80
13702
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
    81
def _collectbrokencsets(repo, files, striprev):
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
    82
    """return the changesets which will be broken by the truncation"""
13705
73cfb7a5aa56 strip: simplify collectone
Matt Mackall <mpm@selenic.com>
parents: 13702
diff changeset
    83
    s = set()
5909
f45f7390c1c5 strip: calculate list of extra nodes to save and pass it to changegroupsubset
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5905
diff changeset
    84
33724
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    85
    s.update(_collectmanifest(repo, striprev))
13705
73cfb7a5aa56 strip: simplify collectone
Matt Mackall <mpm@selenic.com>
parents: 13702
diff changeset
    86
    for fname in files:
33724
6626d12e7a85 repair: refactor broken linkrev collection
Durham Goode <durham@fb.com>
parents: 33490
diff changeset
    87
        s.update(_collectrevlog(repo.file(fname), striprev))
5909
f45f7390c1c5 strip: calculate list of extra nodes to save and pass it to changegroupsubset
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5905
diff changeset
    88
13705
73cfb7a5aa56 strip: simplify collectone
Matt Mackall <mpm@selenic.com>
parents: 13702
diff changeset
    89
    return s
5909
f45f7390c1c5 strip: calculate list of extra nodes to save and pass it to changegroupsubset
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5905
diff changeset
    90
22057
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
    91
def strip(ui, repo, nodelist, backup=True, topic='backup'):
32922
eb84b4ad41e5 repair: clarify in comment that caller must take lock, but not transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 32883
diff changeset
    92
    # This function requires the caller to lock the repo, but it operates
eb84b4ad41e5 repair: clarify in comment that caller must take lock, but not transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 32883
diff changeset
    93
    # within a transaction of its own, and thus requires there to be no current
eb84b4ad41e5 repair: clarify in comment that caller must take lock, but not transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 32883
diff changeset
    94
    # transaction when it is called.
32924
f044295cdb7a repair: move check for existing transaction earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32923
diff changeset
    95
    if repo.currenttransaction() is not None:
f044295cdb7a repair: move check for existing transaction earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32923
diff changeset
    96
        raise error.ProgrammingError('cannot strip from inside a transaction')
f044295cdb7a repair: move check for existing transaction earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32923
diff changeset
    97
22057
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
    98
    # Simple way to maintain backwards compatibility for this
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
    99
    # argument.
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
   100
    if backup in ['none', 'strip']:
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
   101
        backup = False
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
   102
18004
747a2f43d5d9 clfilter: strip logic should be unfiltered
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 17922
diff changeset
   103
    repo = repo.unfiltered()
18310
4499ba5ac35c localrepo: introduce destroying function
Idan Kamara <idankk86@gmail.com>
parents: 18121
diff changeset
   104
    repo.destroying()
17013
c8eda7bbdcab strip: incrementally update the branchheads cache after a strip
Joshua Redstone <joshua.redstone@fb.com>
parents: 16867
diff changeset
   105
5901
16f4129c19ac repair.py: rename chlog to cl
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5900
diff changeset
   106
    cl = repo.changelog
16237
b5c0c7d0f83f repair: remove undo files after strip
Idan Kamara <idankk86@gmail.com>
parents: 15901
diff changeset
   107
    # TODO handle undo of merge sets
16252
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   108
    if isinstance(nodelist, str):
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   109
        nodelist = [nodelist]
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   110
    striplist = [cl.rev(node) for node in nodelist]
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   111
    striprev = min(striplist)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
30707
987dbe87aad6 repair: combine two loops over changelog revisions
Martin von Zweigbergk <martinvonz@google.com>
parents: 30706
diff changeset
   113
    files = _collectfiles(repo, striprev)
987dbe87aad6 repair: combine two loops over changelog revisions
Martin von Zweigbergk <martinvonz@google.com>
parents: 30706
diff changeset
   114
    saverevs = _collectbrokencsets(repo, files, striprev)
987dbe87aad6 repair: combine two loops over changelog revisions
Martin von Zweigbergk <martinvonz@google.com>
parents: 30706
diff changeset
   115
6147
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   116
    # Some revisions with rev > striprev may not be descendants of striprev.
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   117
    # We have to find these revisions and put them in a bundle, so that
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   118
    # we can restore them after the truncations.
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   119
    # To create the bundle we use repo.changegroupsubset which requires
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   120
    # the list of heads and bases of the set of interesting revisions.
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   121
    # (head = revision in the set that has no descendant in the set;
53ae5af55db3 repair.py: rewrite a loop, making it cleaner and faster
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5910
diff changeset
   122
    #  base = revision in the set that has no ancestor in the set)
16252
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   123
    tostrip = set(striplist)
30707
987dbe87aad6 repair: combine two loops over changelog revisions
Martin von Zweigbergk <martinvonz@google.com>
parents: 30706
diff changeset
   124
    saveheads = set(saverevs)
30706
2e4862646f02 repair: speed up stripping of many roots
Martin von Zweigbergk <martinvonz@google.com>
parents: 30375
diff changeset
   125
    for r in cl.revs(start=striprev + 1):
2e4862646f02 repair: speed up stripping of many roots
Martin von Zweigbergk <martinvonz@google.com>
parents: 30375
diff changeset
   126
        if any(p in tostrip for p in cl.parentrevs(r)):
2e4862646f02 repair: speed up stripping of many roots
Martin von Zweigbergk <martinvonz@google.com>
parents: 30375
diff changeset
   127
            tostrip.add(r)
13702
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   128
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   129
        if r not in tostrip:
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   130
            saverevs.add(r)
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   131
            saveheads.difference_update(cl.parentrevs(r))
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   132
            saveheads.add(r)
ffd370aa050b strip: remove usage of extranodes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 13362
diff changeset
   133
    saveheads = [cl.node(r) for r in saveheads]
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   134
15386
6051d8e7e133 strip: backout 73307643a09f (issue3077)
Matt Mackall <mpm@selenic.com>
parents: 15068
diff changeset
   135
    # compute base nodes
6051d8e7e133 strip: backout 73307643a09f (issue3077)
Matt Mackall <mpm@selenic.com>
parents: 15068
diff changeset
   136
    if saverevs:
16867
1093ad1e8903 revlog: descendants(*revs) becomes descendants(revs) (API)
Bryan O'Sullivan <bryano@fb.com>
parents: 16745
diff changeset
   137
        descendants = set(cl.descendants(saverevs))
15386
6051d8e7e133 strip: backout 73307643a09f (issue3077)
Matt Mackall <mpm@selenic.com>
parents: 15068
diff changeset
   138
        saverevs.difference_update(descendants)
6051d8e7e133 strip: backout 73307643a09f (issue3077)
Matt Mackall <mpm@selenic.com>
parents: 15068
diff changeset
   139
    savebases = [cl.node(r) for r in saverevs]
16252
cf17e76be4dd strip: enhance repair.strip to receive a list of nodes (issue3299)
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 15901
diff changeset
   140
    stripbases = [cl.node(r) for r in tostrip]
18040
fe8caf28d580 strip: make query to get new bookmark target cheaper
Siddharth Agarwal <sid0@fb.com>
parents: 18004
diff changeset
   141
32629
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   142
    stripobsidx = obsmarkers = ()
33166
5c9ad50fd62f config: register the 'devel.strip-obsmarkers' config
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 33143
diff changeset
   143
    if repo.ui.configbool('devel', 'strip-obsmarkers'):
33143
d09ae850296d obsutil: move 'exclusivemarkers' to the new modules
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 33108
diff changeset
   144
        obsmarkers = obsutil.exclusivemarkers(repo, stripbases)
32629
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   145
    if obsmarkers:
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   146
        stripobsidx = [i for i, m in enumerate(repo.obsstore)
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   147
                       if m in obsmarkers]
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   148
18040
fe8caf28d580 strip: make query to get new bookmark target cheaper
Siddharth Agarwal <sid0@fb.com>
parents: 18004
diff changeset
   149
    # For a set s, max(parents(s) - s) is the same as max(heads(::s - s)), but
fe8caf28d580 strip: make query to get new bookmark target cheaper
Siddharth Agarwal <sid0@fb.com>
parents: 18004
diff changeset
   150
    # is much faster
fe8caf28d580 strip: make query to get new bookmark target cheaper
Siddharth Agarwal <sid0@fb.com>
parents: 18004
diff changeset
   151
    newbmtarget = repo.revs('max(parents(%ld) - (%ld))', tostrip, tostrip)
17264
ec7b9bec19c9 strip: move bookmarks to nearest ancestor rather than '.'
Augie Fackler <raf@durin42.com>
parents: 17013
diff changeset
   152
    if newbmtarget:
22818
d7b114493315 repair: use `first` instead of direct indexing
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 22057
diff changeset
   153
        newbmtarget = repo[newbmtarget.first()].node()
17264
ec7b9bec19c9 strip: move bookmarks to nearest ancestor rather than '.'
Augie Fackler <raf@durin42.com>
parents: 17013
diff changeset
   154
    else:
ec7b9bec19c9 strip: move bookmarks to nearest ancestor rather than '.'
Augie Fackler <raf@durin42.com>
parents: 17013
diff changeset
   155
        newbmtarget = '.'
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
13362
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   157
    bm = repo._bookmarks
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   158
    updatebm = []
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   159
    for m in bm:
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   160
        rev = repo[bm[m]].rev()
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   161
        if rev in tostrip:
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   162
            updatebm.append(m)
ee01d9d84115 bookmarks: move strip support to repair
Matt Mackall <mpm@selenic.com>
parents: 12057
diff changeset
   163
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   164
    # create a changegroup for all the branches we need to keep
11197
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   165
    backupfile = None
20979
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   166
    vfs = repo.vfs
24252
f962692853c0 repair: define explicit local variable, don't reuse a comprehension variable
Mike Edgar <adgar@google.com>
parents: 24170
diff changeset
   167
    node = nodelist[-1]
22057
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
   168
    if backup:
16388
e03d8a40521f repair: allow giving strip backup a different name
Idan Kamara <idankk86@gmail.com>
parents: 16253
diff changeset
   169
        backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
20979
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   170
        repo.ui.status(_("saved backup bundle to %s\n") %
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   171
                       vfs.join(backupfile))
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   172
        repo.ui.log("backupbundle", "saved backup bundle to %s\n",
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   173
                    vfs.join(backupfile))
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   174
    tmpbundlefile = None
29951
e7acbe538baf strip: simplify some repeated conditions
Martin von Zweigbergk <martinvonz@google.com>
parents: 29708
diff changeset
   175
    if saveheads:
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   176
        # do not compress temporary bundle if we remove it from disk later
32628
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   177
        #
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   178
        # We do not include obsolescence, it might re-introduce prune markers
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   179
        # we are trying to strip.  This is harmless since the stripped markers
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   180
        # are already backed up and we did not touched the markers for the
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   181
        # saved changesets.
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   182
        tmpbundlefile = _bundle(repo, savebases, saveheads, node, 'temp',
32628
5732e6d2b369 strip: do not include obsolescence markers for the temporary bundle
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32623
diff changeset
   183
                                compress=False, obsolescence=False)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   184
27873
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   185
    try:
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   186
        with repo.transaction("strip") as tr:
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   187
            offset = len(tr.entries)
8073
e8a28556a0a8 strip: make repair.strip transactional to avoid repository corruption
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 7361
diff changeset
   188
27873
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   189
            tr.startgroup()
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   190
            cl.strip(striprev, tr)
33725
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   191
            stripmanifest(repo, striprev, tr, files)
32196
a2be2abe9476 strip: move tree strip logic to it's own function
Durham Goode <durham@fb.com>
parents: 31875
diff changeset
   192
27873
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   193
            for fn in files:
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   194
                repo.file(fn).strip(striprev, tr)
60ea60fea5f3 with: use context manager for transaction in strip
Bryan O'Sullivan <bryano@fb.com>
parents: 27871
diff changeset
   195
            tr.endgroup()
8073
e8a28556a0a8 strip: make repair.strip transactional to avoid repository corruption
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 7361
diff changeset
   196
11197
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   197
            for i in xrange(offset, len(tr.entries)):
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   198
                file, troffset, ignore = tr.entries[i]
30001
e38d85be978f repair: open a file with checkambig=True to avoid file stat ambiguity
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29954
diff changeset
   199
                with repo.svfs(file, 'a', checkambig=True) as fp:
e38d85be978f repair: open a file with checkambig=True to avoid file stat ambiguity
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 29954
diff changeset
   200
                    fp.truncate(troffset)
20885
f49d60fa40a5 fncache: clean up fncache during strips
Durham Goode <durham@fb.com>
parents: 20074
diff changeset
   201
                if troffset == 0:
f49d60fa40a5 fncache: clean up fncache during strips
Durham Goode <durham@fb.com>
parents: 20074
diff changeset
   202
                    repo.store.markremoved(file)
11197
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   203
32629
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   204
            deleteobsmarkers(repo.obsstore, stripobsidx)
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   205
            del repo.obsstore
35778
128dd940bedc repair: invalidate volatile sets after stripping
Martin von Zweigbergk <martinvonz@google.com>
parents: 35707
diff changeset
   206
            repo.invalidatevolatilesets()
35707
54074a82e050 repair: filter out unknown revisions from phasecache within transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 35706
diff changeset
   207
            repo._phasecache.filterunknown(repo)
32629
71eb6a098315 strip: strip obsmarkers exclusive to the stripped changeset
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 32628
diff changeset
   208
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   209
        if tmpbundlefile:
11202
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   210
            ui.note(_("adding branch\n"))
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   211
            f = vfs.open(tmpbundlefile, "rb")
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   212
            gen = exchange.readbundle(ui, f, tmpbundlefile, vfs)
11202
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   213
            if not repo.ui.verbose:
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   214
                # silence internal shuffling chatter
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   215
                repo.ui.pushbuffer()
32929
d11e2343762b repair: create transaction for bundle1 unbundling earlier
Martin von Zweigbergk <martinvonz@google.com>
parents: 32925
diff changeset
   216
            tmpbundleurl = 'bundle:' + vfs.join(tmpbundlefile)
33042
dbc2ee17053e bundle: transpose transaction scope with bundle type switch
Martin von Zweigbergk <martinvonz@google.com>
parents: 33039
diff changeset
   217
            txnname = 'strip'
dbc2ee17053e bundle: transpose transaction scope with bundle type switch
Martin von Zweigbergk <martinvonz@google.com>
parents: 33039
diff changeset
   218
            if not isinstance(gen, bundle2.unbundle20):
dbc2ee17053e bundle: transpose transaction scope with bundle type switch
Martin von Zweigbergk <martinvonz@google.com>
parents: 33039
diff changeset
   219
                txnname = "strip\n%s" % util.hidepassword(tmpbundleurl)
dbc2ee17053e bundle: transpose transaction scope with bundle type switch
Martin von Zweigbergk <martinvonz@google.com>
parents: 33039
diff changeset
   220
            with repo.transaction(txnname) as tr:
33043
18c2489ac96d bundle: make applybundle() delegate v1 bundles to applybundle1()
Martin von Zweigbergk <martinvonz@google.com>
parents: 33042
diff changeset
   221
                bundle2.applybundle(repo, gen, tr, source='strip',
33307
665271d601f5 strip: don't allow empty changegroup in bundle1
Martin von Zweigbergk <martinvonz@google.com>
parents: 33166
diff changeset
   222
                                    url=tmpbundleurl)
11202
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   223
            if not repo.ui.verbose:
f974fe896921 strip: hide unbundle messages by default
Matt Mackall <mpm@selenic.com>
parents: 11200
diff changeset
   224
                repo.ui.popbuffer()
11197
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   225
            f.close()
31626
0febf8e4e2ce repair: use context manager for lock management
Matt Harbison <matt_harbison@yahoo.com>
parents: 31324
diff changeset
   226
32925
4c6e4a4486a0 repair: remove unnecessary locking for bookmarks
Martin von Zweigbergk <martinvonz@google.com>
parents: 32924
diff changeset
   227
        with repo.transaction('repair') as tr:
33490
902fe63954a9 bookmark: use 'applychanges' in 'repair.strip'
Boris Feld <boris.feld@octobus.net>
parents: 33307
diff changeset
   228
            bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm]
902fe63954a9 bookmark: use 'applychanges' in 'repair.strip'
Boris Feld <boris.feld@octobus.net>
parents: 33307
diff changeset
   229
            bm.applychanges(repo, tr, bmchanges)
27157
5f2e4eb08e41 repair: use bookmarks.recordchange instead of bookmarks.write
Laurent Charignon <lcharignon@fb.com>
parents: 26797
diff changeset
   230
16237
b5c0c7d0f83f repair: remove undo files after strip
Idan Kamara <idankk86@gmail.com>
parents: 15901
diff changeset
   231
        # remove undo files
20975
37cdf1fca1b2 localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20933
diff changeset
   232
        for undovfs, undofile in repo.undofiles():
16237
b5c0c7d0f83f repair: remove undo files after strip
Idan Kamara <idankk86@gmail.com>
parents: 15901
diff changeset
   233
            try:
20975
37cdf1fca1b2 localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20933
diff changeset
   234
                undovfs.unlink(undofile)
25660
328739ea70c3 global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25652
diff changeset
   235
            except OSError as e:
16237
b5c0c7d0f83f repair: remove undo files after strip
Idan Kamara <idankk86@gmail.com>
parents: 15901
diff changeset
   236
                if e.errno != errno.ENOENT:
20975
37cdf1fca1b2 localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20933
diff changeset
   237
                    ui.warn(_('error removing %s: %s\n') %
37cdf1fca1b2 localrepo: make "undofiles()" return list of tuples "(vfs, relative filename)"
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20933
diff changeset
   238
                            (undovfs.join(undofile), str(e)))
16237
b5c0c7d0f83f repair: remove undo files after strip
Idan Kamara <idankk86@gmail.com>
parents: 15901
diff changeset
   239
16705
c2d9ef43ff6c check-code: ignore naked excepts with a "re-raise" comment
Brodie Rao <brodie@sf.io>
parents: 16628
diff changeset
   240
    except: # re-raises
11197
4bb4895e1693 strip: be quiet about temporary internal bundle
Matt Mackall <mpm@selenic.com>
parents: 10881
diff changeset
   241
        if backupfile:
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   242
            ui.warn(_("strip failed, backup bundle stored in '%s'\n")
20979
ad5b61370514 repair: make "strip()" treat bundle files via vfs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 20977
diff changeset
   243
                    % vfs.join(backupfile))
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   244
        if tmpbundlefile:
29953
94ebf56db04e strip: clarify that user action is required to recover temp bundle
Martin von Zweigbergk <martinvonz@google.com>
parents: 29952
diff changeset
   245
            ui.warn(_("strip failed, unrecovered changes stored in '%s'\n")
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   246
                    % vfs.join(tmpbundlefile))
29953
94ebf56db04e strip: clarify that user action is required to recover temp bundle
Martin von Zweigbergk <martinvonz@google.com>
parents: 29952
diff changeset
   247
            ui.warn(_("(fix the problem, then recover the changesets with "
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   248
                      "\"hg unbundle '%s'\")\n") % vfs.join(tmpbundlefile))
8073
e8a28556a0a8 strip: make repair.strip transactional to avoid repository corruption
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 7361
diff changeset
   249
        raise
22057
445472225ccd strip: remove -b/--backup codepaths
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents: 21064
diff changeset
   250
    else:
29954
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   251
        if tmpbundlefile:
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   252
            # Remove temporary bundle only if there were no exceptions
769aee32fae0 strip: don't use "full" and "partial" to describe bundles
Martin von Zweigbergk <martinvonz@google.com>
parents: 29953
diff changeset
   253
            vfs.unlink(tmpbundlefile)
4702
18e91c9def0c strip: move strip code to a new repair module
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   254
18395
904b7109938e destroyed: drop complex branchcache rebuilt logic
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 18311
diff changeset
   255
    repo.destroyed()
30274
c1345969f6c5 repair: make strip() return backup file path
Martin von Zweigbergk <martinvonz@google.com>
parents: 30001
diff changeset
   256
    # return the backup file path (or None if 'backup' was False) so
c1345969f6c5 repair: make strip() return backup file path
Martin von Zweigbergk <martinvonz@google.com>
parents: 30001
diff changeset
   257
    # extensions can use it
c1345969f6c5 repair: make strip() return backup file path
Martin von Zweigbergk <martinvonz@google.com>
parents: 30001
diff changeset
   258
    return backupfile
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   259
33087
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   260
def safestriproots(ui, repo, nodes):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   261
    """return list of roots of nodes where descendants are covered by nodes"""
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   262
    torev = repo.unfiltered().changelog.rev
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   263
    revs = set(torev(n) for n in nodes)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   264
    # tostrip = wanted - unsafe = wanted - ancestors(orphaned)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   265
    # orphaned = affected - wanted
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   266
    # affected = descendants(roots(wanted))
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   267
    # wanted = revs
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   268
    tostrip = set(repo.revs('%ld-(::((roots(%ld)::)-%ld))', revs, revs, revs))
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   269
    notstrip = revs - tostrip
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   270
    if notstrip:
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   271
        nodestr = ', '.join(sorted(short(repo[n].node()) for n in notstrip))
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   272
        ui.warn(_('warning: orphaned descendants detected, '
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   273
                  'not stripping %s\n') % nodestr)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   274
    return [c.node() for c in repo.set('roots(%ld)', tostrip)]
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   275
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   276
class stripcallback(object):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   277
    """used as a transaction postclose callback"""
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   278
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   279
    def __init__(self, ui, repo, backup, topic):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   280
        self.ui = ui
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   281
        self.repo = repo
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   282
        self.backup = backup
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   283
        self.topic = topic or 'backup'
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   284
        self.nodelist = []
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   285
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   286
    def addnodes(self, nodes):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   287
        self.nodelist.extend(nodes)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   288
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   289
    def __call__(self, tr):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   290
        roots = safestriproots(self.ui, self.repo, self.nodelist)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   291
        if roots:
33108
208de1534ebd strip: respect the backup option in stripcallback
Jun Wu <quark@fb.com>
parents: 33087
diff changeset
   292
            strip(self.ui, self.repo, roots, self.backup, self.topic)
33087
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   293
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   294
def delayedstrip(ui, repo, nodelist, topic=None):
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   295
    """like strip, but works inside transaction and won't strip irreverent revs
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   296
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   297
    nodelist must explicitly contain all descendants. Otherwise a warning will
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   298
    be printed that some nodes are not stripped.
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   299
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   300
    Always do a backup. The last non-None "topic" will be used as the backup
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   301
    topic name. The default backup topic name is "backup".
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   302
    """
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   303
    tr = repo.currenttransaction()
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   304
    if not tr:
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   305
        nodes = safestriproots(ui, repo, nodelist)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   306
        return strip(ui, repo, nodes, True, topic)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   307
    # transaction postclose callbacks are called in alphabet order.
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   308
    # use '\xff' as prefix so we are likely to be called last.
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   309
    callback = tr.getpostclose('\xffstrip')
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   310
    if callback is None:
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   311
        callback = stripcallback(ui, repo, True, topic)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   312
        tr.addpostclose('\xffstrip', callback)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   313
    if topic:
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   314
        callback.topic = topic
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   315
    callback.addnodes(nodelist)
fcd1c483f5ea strip: add a delayedstrip method that works in a transaction
Jun Wu <quark@fb.com>
parents: 33043
diff changeset
   316
33725
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   317
def stripmanifest(repo, striprev, tr, files):
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   318
    revlog = repo.manifestlog._revlog
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   319
    revlog.strip(striprev, tr)
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   320
    striptrees(repo, tr, striprev, files)
86ea201eaeb9 repair: move manifest strip to a separate function
Durham Goode <durham@fb.com>
parents: 33724
diff changeset
   321
32196
a2be2abe9476 strip: move tree strip logic to it's own function
Durham Goode <durham@fb.com>
parents: 31875
diff changeset
   322
def striptrees(repo, tr, striprev, files):
a2be2abe9476 strip: move tree strip logic to it's own function
Durham Goode <durham@fb.com>
parents: 31875
diff changeset
   323
    if 'treemanifest' in repo.requirements: # safe but unnecessary
a2be2abe9476 strip: move tree strip logic to it's own function
Durham Goode <durham@fb.com>
parents: 31875
diff changeset
   324
                                            # otherwise
32296
7e07d5836063 hg: backout optimizing for treemanifests
Durham Goode <durham@fb.com>
parents: 32197
diff changeset
   325
        for unencoded, encoded, size in repo.store.datafiles():
7e07d5836063 hg: backout optimizing for treemanifests
Durham Goode <durham@fb.com>
parents: 32197
diff changeset
   326
            if (unencoded.startswith('meta/') and
7e07d5836063 hg: backout optimizing for treemanifests
Durham Goode <durham@fb.com>
parents: 32197
diff changeset
   327
                unencoded.endswith('00manifest.i')):
7e07d5836063 hg: backout optimizing for treemanifests
Durham Goode <durham@fb.com>
parents: 32197
diff changeset
   328
                dir = unencoded[5:-12]
7e07d5836063 hg: backout optimizing for treemanifests
Durham Goode <durham@fb.com>
parents: 32197
diff changeset
   329
                repo.manifestlog._revlog.dirlog(dir).strip(striprev, tr)
32196
a2be2abe9476 strip: move tree strip logic to it's own function
Durham Goode <durham@fb.com>
parents: 31875
diff changeset
   330
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   331
def rebuildfncache(ui, repo):
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   332
    """Rebuilds the fncache file from repo history.
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   333
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   334
    Missing entries will be added. Extra entries will be removed.
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   335
    """
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   336
    repo = repo.unfiltered()
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   337
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   338
    if 'fncache' not in repo.requirements:
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   339
        ui.warn(_('(not rebuilding fncache because repository does not '
25874
3e84f40232c7 repair: fix typo in warning message
Wagner Bruna <wbruna@yahoo.com>
parents: 25845
diff changeset
   340
                  'support fncache)\n'))
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   341
        return
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   342
27860
0da102e4f203 with: use context manager in rebuildfncache again
Bryan O'Sullivan <bryano@fb.com>
parents: 27553
diff changeset
   343
    with repo.lock():
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   344
        fnc = repo.store.fncache
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   345
        # Trigger load of fncache.
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   346
        if 'irrelevant' in fnc:
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   347
            pass
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   348
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   349
        oldentries = set(fnc.entries)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   350
        newentries = set()
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   351
        seenfiles = set()
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   352
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   353
        repolen = len(repo)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   354
        for rev in repo:
28466
c7d45c5a8cea repair: specify unit for ui.progress in rebuildfncache()
Anton Shestakov <av6@dwimlabs.net>
parents: 28465
diff changeset
   355
            ui.progress(_('rebuilding'), rev, total=repolen,
c7d45c5a8cea repair: specify unit for ui.progress in rebuildfncache()
Anton Shestakov <av6@dwimlabs.net>
parents: 28465
diff changeset
   356
                        unit=_('changesets'))
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   357
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   358
            ctx = repo[rev]
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   359
            for f in ctx.files():
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   360
                # This is to minimize I/O.
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   361
                if f in seenfiles:
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   362
                    continue
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   363
                seenfiles.add(f)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   364
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   365
                i = 'data/%s.i' % f
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   366
                d = 'data/%s.d' % f
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   367
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   368
                if repo.store._exists(i):
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   369
                    newentries.add(i)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   370
                if repo.store._exists(d):
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   371
                    newentries.add(d)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   372
28465
43eb31ea2dcb repair: use 'rebuilding' progress topic in rebuildfncache()
Anton Shestakov <av6@dwimlabs.net>
parents: 28031
diff changeset
   373
        ui.progress(_('rebuilding'), None)
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   374
28031
6f248ba85309 treemanifest: fix debugrebuildfncache
Martin von Zweigbergk <martinvonz@google.com>
parents: 28007
diff changeset
   375
        if 'treemanifest' in repo.requirements: # safe but unnecessary otherwise
28007
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   376
            for dir in util.dirs(seenfiles):
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   377
                i = 'meta/%s/00manifest.i' % dir
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   378
                d = 'meta/%s/00manifest.d' % dir
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   379
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   380
                if repo.store._exists(i):
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   381
                    newentries.add(i)
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   382
                if repo.store._exists(d):
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   383
                    newentries.add(d)
fb92927f9775 treemanifests: fix streaming clone
Martin von Zweigbergk <martinvonz@google.com>
parents: 27930
diff changeset
   384
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   385
        addcount = len(newentries - oldentries)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   386
        removecount = len(oldentries - newentries)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   387
        for p in sorted(oldentries - newentries):
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   388
            ui.write(_('removing %s\n') % p)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   389
        for p in sorted(newentries - oldentries):
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   390
            ui.write(_('adding %s\n') % p)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   391
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   392
        if addcount or removecount:
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   393
            ui.write(_('%d items added, %d removed from fncache\n') %
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   394
                     (addcount, removecount))
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   395
            fnc.entries = newentries
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   396
            fnc._dirty = True
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   397
27871
f1c316fd91f9 with: use context manager in rebuildfncache
Bryan O'Sullivan <bryano@fb.com>
parents: 27860
diff changeset
   398
            with repo.transaction('fncache') as tr:
25652
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   399
                fnc.write(tr)
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   400
        else:
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   401
            ui.write(_('fncache already up to date\n'))
2882d6886919 repair: add functionality to rebuild fncache
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25404
diff changeset
   402
26624
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   403
def stripbmrevset(repo, mark):
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   404
    """
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   405
    The revset to strip when strip is called with -B mark
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   406
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   407
    Needs to live here so extensions can use it and wrap it even when strip is
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   408
    not enabled or not present on a box.
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   409
    """
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   410
    return repo.revs("ancestors(bookmark(%s)) - "
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   411
                     "ancestors(head() and not bookmark(%s)) - "
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   412
                     "ancestors(bookmark() and not bookmark(%s))",
bcace0fbb4c8 strip: factor out revset calculation for strip -B
Ryan McElroy <rmcelroy@fb.com>
parents: 26587
diff changeset
   413
                     mark, mark, mark)
28868
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   414
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   415
def deleteobsmarkers(obsstore, indices):
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   416
    """Delete some obsmarkers from obsstore and return how many were deleted
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   417
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   418
    'indices' is a list of ints which are the indices
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   419
    of the markers to be deleted.
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   420
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   421
    Every invocation of this function completely rewrites the obsstore file,
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   422
    skipping the markers we want to be removed. The new temporary file is
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   423
    created, remaining markers are written there and on .close() this file
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   424
    gets atomically renamed to obsstore, thus guaranteeing consistency."""
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   425
    if not indices:
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   426
        # we don't want to rewrite the obsstore with the same content
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   427
        return
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   428
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   429
    left = []
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   430
    current = obsstore._all
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   431
    n = 0
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   432
    for i, m in enumerate(current):
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   433
        if i in indices:
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   434
            n += 1
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   435
            continue
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   436
        left.append(m)
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   437
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   438
    newobsstorefile = obsstore.svfs('obsstore', 'w', atomictemp=True)
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   439
    for bytes in obsolete.encodemarkers(left, True, obsstore._version):
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   440
        newobsstorefile.write(bytes)
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   441
    newobsstorefile.close()
445a25bb70be obsstore: move delete function from obsstore class to repair module
Kostia Balytskyi <ikostia@fb.com>
parents: 28666
diff changeset
   442
    return n