mercurial/manifest.py
author Drew Gottlieb <drgott@google.com>
Mon, 06 Apr 2015 10:51:53 -0700
changeset 24636 36872036169b
parent 24635 21e1ece30f8c
child 24646 5693c834bcb4
permissions -rw-r--r--
treemanifest: further optimize treemanifest.matches() The matches function was previously traversing all submanifests to look for matching files, even though it was possible to know if a submanifest won't contain any matches. This change adds a visitdir function on the match object to decide quickly if a directory should be visited when traversing. The function also decides if _all_ subdirectories should be traversed. Adding this logic as methods on the match object also makes the logic modifiable by extensions, such as largefiles. An example of a command this speeds up is running hg status --rev .^ python/ on the Mozilla repo with the treemanifest experiment enabled. It goes from 2.03s to 1.85s. More improvements to speed from this change will happen when treemanifests are lazily loaded. Because a flat manifest is still loaded and then converted into treemanifests, speed improvements are limited. This change has no negative effect on speed. For a worst-case example, this command is not negatively impacted: hg status --rev .^ 'relglob:*.js' on the Mozilla repo. It goes from 2.83s to 2.82s.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1089
142b5d5ec9cc Break apart hg.py
mpm@selenic.com
parents: 1072
diff changeset
     1
# manifest.py - manifest revision class for mercurial
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     2
#
4635
63b9d2deed48 Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents: 4633
diff changeset
     3
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8209
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9420
diff changeset
     6
# GNU General Public License version 2 or any later version.
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
     7
3891
6b4127c7d52a Simplify i18n imports
Matt Mackall <mpm@selenic.com>
parents: 3877
diff changeset
     8
from i18n import _
24635
21e1ece30f8c util: move dirs() and finddirs() from scmutil to util
Drew Gottlieb <drgott@google.com>
parents: 24600
diff changeset
     9
import mdiff, parsers, error, revlog, util
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
    10
import array, struct
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    11
import os
79
837d473d54d5 Add basic annotation support
mpm@selenic.com
parents: 78
diff changeset
    12
24322
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
    13
propertycache = util.propertycache
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
    14
24572
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    15
def _parsev1(data):
24524
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    16
    # This method does a little bit of excessive-looking
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    17
    # precondition checking. This is so that the behavior of this
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    18
    # class exactly matches its C counterpart to try and help
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    19
    # prevent surprise breakage for anyone that develops against
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    20
    # the pure version.
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    21
    if data and data[-1] != '\n':
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    22
        raise ValueError('Manifest did not end in a newline.')
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    23
    prev = None
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    24
    for l in data.splitlines():
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    25
        if prev is not None and prev > l:
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    26
            raise ValueError('Manifest lines not in sorted order.')
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    27
        prev = l
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    28
        f, n = l.split('\0')
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    29
        if len(n) > 40:
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    30
            yield f, revlog.bin(n[:40]), n[40:]
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    31
        else:
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    32
            yield f, revlog.bin(n), ''
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
    33
24572
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    34
def _parsev2(data):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    35
    metadataend = data.find('\n')
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    36
    # Just ignore metadata for now
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    37
    pos = metadataend + 1
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    38
    prevf = ''
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    39
    while pos < len(data):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    40
        end = data.find('\n', pos + 1) # +1 to skip stem length byte
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    41
        if end == -1:
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    42
            raise ValueError('Manifest ended with incomplete file entry.')
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    43
        stemlen = ord(data[pos])
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    44
        items = data[pos + 1:end].split('\0')
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    45
        f = prevf[:stemlen] + items[0]
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    46
        if prevf > f:
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    47
            raise ValueError('Manifest entries not in sorted order.')
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    48
        fl = items[1]
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    49
        # Just ignore metadata (items[2:] for now)
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    50
        n = data[end + 1:end + 21]
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    51
        yield f, n, fl
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    52
        pos = end + 22
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    53
        prevf = f
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    54
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    55
def _parse(data):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    56
    """Generates (path, node, flags) tuples from a manifest text"""
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    57
    if data.startswith('\0'):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    58
        return iter(_parsev2(data))
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    59
    else:
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    60
        return iter(_parsev1(data))
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
    61
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    62
def _text(it, usemanifestv2):
24525
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    63
    """Given an iterator over (path, node, flags) tuples, returns a manifest
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    64
    text"""
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    65
    if usemanifestv2:
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    66
        return _textv2(it)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    67
    else:
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    68
        return _textv1(it)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    69
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    70
def _textv1(it):
24525
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    71
    files = []
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    72
    lines = []
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    73
    _hex = revlog.hex
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    74
    for f, n, fl in it:
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    75
        files.append(f)
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    76
        # if this is changed to support newlines in filenames,
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    77
        # be sure to check the templates/ dir again (especially *-raw.tmpl)
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    78
        lines.append("%s\0%s%s\n" % (f, _hex(n), fl))
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    79
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    80
    _checkforbidden(files)
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    81
    return ''.join(lines)
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
    82
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    83
def _textv2(it):
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    84
    files = []
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    85
    lines = ['\0\n']
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    86
    prevf = ''
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    87
    for f, n, fl in it:
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    88
        files.append(f)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    89
        stem = os.path.commonprefix([prevf, f])
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    90
        stemlen = min(len(stem), 255)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    91
        lines.append("%c%s\0%s\n%s\n" % (stemlen, f[stemlen:], fl, n))
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    92
        prevf = f
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    93
    _checkforbidden(files)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    94
    return ''.join(lines)
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
    95
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
    96
class _lazymanifest(dict):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
    97
    """This is the pure implementation of lazymanifest.
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
    98
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
    99
    It has not been optimized *at all* and is not lazy.
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   100
    """
24223
b4df0d0c49e7 manifest: move parsing functions up in file
Augie Fackler <augie@google.com>
parents: 24215
diff changeset
   101
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   102
    def __init__(self, data):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   103
        dict.__init__(self)
24524
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
   104
        for f, n, fl in _parse(data):
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
   105
            self[f] = n, fl
24224
d71837d06597 manifest: do parsing inside manifestdict contstructor
Augie Fackler <augie@google.com>
parents: 24223
diff changeset
   106
23594
6f53629ad273 manifest: disallow setting the node id of an entry to None
Augie Fackler <augie@google.com>
parents: 22966
diff changeset
   107
    def __setitem__(self, k, v):
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   108
        node, flag = v
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   109
        assert node is not None
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   110
        if len(node) > 21:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   111
            node = node[:21] # match c implementation behavior
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   112
        dict.__setitem__(self, k, (node, flag))
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   113
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   114
    def __iter__(self):
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   115
        return iter(sorted(dict.keys(self)))
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   116
24297
0178f500d61e lazymanifest: fix pure hg iterkeys()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24295
diff changeset
   117
    def iterkeys(self):
0178f500d61e lazymanifest: fix pure hg iterkeys()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24295
diff changeset
   118
        return iter(sorted(dict.keys(self)))
0178f500d61e lazymanifest: fix pure hg iterkeys()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24295
diff changeset
   119
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   120
    def iterentries(self):
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   121
        return ((f, e[0], e[1]) for f, e in sorted(self.iteritems()))
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   122
2831
0b50a580be36 Add manifestflags class
Matt Mackall <mpm@selenic.com>
parents: 2470
diff changeset
   123
    def copy(self):
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   124
        c = _lazymanifest('')
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   125
        c.update(self)
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   126
        return c
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   127
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   128
    def diff(self, m2, clean=False):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   129
        '''Finds changes between the current manifest and m2.'''
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   130
        diff = {}
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   131
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   132
        for fn, e1 in self.iteritems():
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   133
            if fn not in m2:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   134
                diff[fn] = e1, (None, '')
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   135
            else:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   136
                e2 = m2[fn]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   137
                if e1 != e2:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   138
                    diff[fn] = e1, e2
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   139
                elif clean:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   140
                    diff[fn] = None
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   141
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   142
        for fn, e2 in m2.iteritems():
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   143
            if fn not in self:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   144
                diff[fn] = (None, ''), e2
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   145
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   146
        return diff
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   147
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   148
    def filtercopy(self, filterfn):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   149
        c = _lazymanifest('')
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   150
        for f, n, fl in self.iterentries():
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   151
            if filterfn(f):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   152
                c[f] = n, fl
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   153
        return c
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   154
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   155
    def text(self):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   156
        """Get the full data of this manifest as a bytestring."""
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   157
        return _textv1(self.iterentries())
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   158
24226
b992769dd1be manifest: use custom C implementation of lazymanifest
Augie Fackler <augie@google.com>
parents: 24225
diff changeset
   159
try:
b992769dd1be manifest: use custom C implementation of lazymanifest
Augie Fackler <augie@google.com>
parents: 24225
diff changeset
   160
    _lazymanifest = parsers.lazymanifest
b992769dd1be manifest: use custom C implementation of lazymanifest
Augie Fackler <augie@google.com>
parents: 24225
diff changeset
   161
except AttributeError:
b992769dd1be manifest: use custom C implementation of lazymanifest
Augie Fackler <augie@google.com>
parents: 24225
diff changeset
   162
    pass
b992769dd1be manifest: use custom C implementation of lazymanifest
Augie Fackler <augie@google.com>
parents: 24225
diff changeset
   163
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   164
class manifestdict(object):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   165
    def __init__(self, data=''):
24572
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   166
        if data.startswith('\0'):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   167
            #_lazymanifest can not parse v2
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   168
            self._lm = _lazymanifest('')
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   169
            for f, n, fl in _parsev2(data):
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   170
                self._lm[f] = n, fl
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   171
        else:
b83679eb5f86 manifestv2: add support for reading new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24571
diff changeset
   172
            self._lm = _lazymanifest(data)
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   173
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   174
    def __getitem__(self, key):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   175
        return self._lm[key][0]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   176
24277
22d560fe1516 manifest: don't let find() look inside manifestdict
Martin von Zweigbergk <martinvonz@google.com>
parents: 24226
diff changeset
   177
    def find(self, key):
22d560fe1516 manifest: don't let find() look inside manifestdict
Martin von Zweigbergk <martinvonz@google.com>
parents: 24226
diff changeset
   178
        return self._lm[key]
22d560fe1516 manifest: don't let find() look inside manifestdict
Martin von Zweigbergk <martinvonz@google.com>
parents: 24226
diff changeset
   179
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   180
    def __len__(self):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   181
        return len(self._lm)
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   182
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   183
    def __setitem__(self, key, node):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   184
        self._lm[key] = node, self.flags(key, '')
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   185
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   186
    def __contains__(self, key):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   187
        return key in self._lm
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   188
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   189
    def __delitem__(self, key):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   190
        del self._lm[key]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   191
24295
2b7ab29627fd lazymanifest: add iterkeys() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24292
diff changeset
   192
    def __iter__(self):
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   193
        return self._lm.__iter__()
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   194
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   195
    def iterkeys(self):
24295
2b7ab29627fd lazymanifest: add iterkeys() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24292
diff changeset
   196
        return self._lm.iterkeys()
2b7ab29627fd lazymanifest: add iterkeys() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24292
diff changeset
   197
2b7ab29627fd lazymanifest: add iterkeys() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24292
diff changeset
   198
    def keys(self):
2b7ab29627fd lazymanifest: add iterkeys() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24292
diff changeset
   199
        return list(self.iterkeys())
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   200
24495
d2a3a2808974 manifest: make manifest.intersectfiles() internal
Drew Gottlieb <drgott@google.com>
parents: 24467
diff changeset
   201
    def _intersectfiles(self, files):
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   202
        '''make a new lazymanifest with the intersection of self with files
21879
090dcaaf3fff manifestdict: add a new method to intersect with a set of files
Siddharth Agarwal <sid0@fb.com>
parents: 20075
diff changeset
   203
090dcaaf3fff manifestdict: add a new method to intersect with a set of files
Siddharth Agarwal <sid0@fb.com>
parents: 20075
diff changeset
   204
        The algorithm assumes that files is much smaller than self.'''
090dcaaf3fff manifestdict: add a new method to intersect with a set of files
Siddharth Agarwal <sid0@fb.com>
parents: 20075
diff changeset
   205
        ret = manifestdict()
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   206
        lm = self._lm
21879
090dcaaf3fff manifestdict: add a new method to intersect with a set of files
Siddharth Agarwal <sid0@fb.com>
parents: 20075
diff changeset
   207
        for fn in files:
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   208
            if fn in lm:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   209
                ret._lm[fn] = self._lm[fn]
21879
090dcaaf3fff manifestdict: add a new method to intersect with a set of files
Siddharth Agarwal <sid0@fb.com>
parents: 20075
diff changeset
   210
        return ret
22964
2793ecb1522d manifest: repurpose flagsdiff() into (node-and-flag)diff()
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 22943
diff changeset
   211
24184
cd66080ef6d4 copies: move code into new manifestdict.filesnotin() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24147
diff changeset
   212
    def filesnotin(self, m2):
cd66080ef6d4 copies: move code into new manifestdict.filesnotin() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24147
diff changeset
   213
        '''Set of files in this manifest that are not in the other'''
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   214
        files = set(self)
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   215
        files.difference_update(m2)
24184
cd66080ef6d4 copies: move code into new manifestdict.filesnotin() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24147
diff changeset
   216
        return files
cd66080ef6d4 copies: move code into new manifestdict.filesnotin() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 24147
diff changeset
   217
24322
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   218
    @propertycache
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   219
    def _dirs(self):
24635
21e1ece30f8c util: move dirs() and finddirs() from scmutil to util
Drew Gottlieb <drgott@google.com>
parents: 24600
diff changeset
   220
        return util.dirs(self)
24322
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   221
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   222
    def dirs(self):
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   223
        return self._dirs
f263814c72ac manifest: add dirs() to manifestdict
Drew Gottlieb <drgott@google.com>
parents: 24298
diff changeset
   224
24324
149cc171e4a0 manifest: add manifestdict.hasdir() method
Drew Gottlieb <drgott@google.com>
parents: 24322
diff changeset
   225
    def hasdir(self, dir):
149cc171e4a0 manifest: add manifestdict.hasdir() method
Drew Gottlieb <drgott@google.com>
parents: 24322
diff changeset
   226
        return dir in self._dirs
149cc171e4a0 manifest: add manifestdict.hasdir() method
Drew Gottlieb <drgott@google.com>
parents: 24322
diff changeset
   227
23305
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   228
    def matches(self, match):
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   229
        '''generate a new manifest filtered by the match argument'''
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   230
        if match.always():
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   231
            return self.copy()
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   232
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   233
        files = match.files()
24448
55c449345b10 match: add isexact() method to hide internals
Martin von Zweigbergk <martinvonz@google.com>
parents: 24406
diff changeset
   234
        if (len(files) < 100 and (match.isexact() or
24396
9e03602cd2d8 manifest: avoid intersectfiles for matches > 100 files
Durham Goode <durham@fb.com>
parents: 24350
diff changeset
   235
            (not match.anypats() and util.all(fn in self for fn in files)))):
24495
d2a3a2808974 manifest: make manifest.intersectfiles() internal
Drew Gottlieb <drgott@google.com>
parents: 24467
diff changeset
   236
            return self._intersectfiles(files)
23305
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   237
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   238
        lm = manifestdict('')
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   239
        lm._lm = self._lm.filtercopy(match)
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   240
        return lm
23305
0cc283f44655 manifest: add matches() method
Martin von Zweigbergk <martinvonz@google.com>
parents: 22966
diff changeset
   241
23756
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   242
    def diff(self, m2, clean=False):
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   243
        '''Finds changes between the current manifest and m2.
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   244
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   245
        Args:
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   246
          m2: the manifest to which this manifest should be compared.
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   247
          clean: if true, include files unchanged between these manifests
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   248
                 with a None value in the returned dictionary.
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   249
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   250
        The result is returned as a dict with filename as key and
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   251
        values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   252
        nodeid in the current/other manifest and fl1/fl2 is the flag
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   253
        in the current/other manifest. Where the file does not exist,
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   254
        the nodeid will be None and the flags will be the empty
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   255
        string.
829f640b5540 manifest: add optional recording of clean entries to diff
Augie Fackler <augie@google.com>
parents: 23602
diff changeset
   256
        '''
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   257
        return self._lm.diff(m2._lm, clean)
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   258
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   259
    def setflag(self, key, flag):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   260
        self._lm[key] = self[key], flag
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   261
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   262
    def get(self, key, default=None):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   263
        try:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   264
            return self._lm[key][0]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   265
        except KeyError:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   266
            return default
22965
b697fa74b475 manifest: for diff(), only iterate over files, not flags
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 22964
diff changeset
   267
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   268
    def flags(self, key, default=''):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   269
        try:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   270
            return self._lm[key][1]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   271
        except KeyError:
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   272
            return default
22965
b697fa74b475 manifest: for diff(), only iterate over files, not flags
Martin von Zweigbergk <martinvonz@gmail.com>
parents: 22964
diff changeset
   273
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   274
    def copy(self):
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   275
        c = manifestdict('')
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   276
        c._lm = self._lm.copy()
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   277
        return c
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   278
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   279
    def iteritems(self):
24298
49cd847fd69a lazymanifest: make __iter__ generate filenames, not 3-tuples
Martin von Zweigbergk <martinvonz@google.com>
parents: 24297
diff changeset
   280
        return (x[:2] for x in self._lm.iterentries())
2831
0b50a580be36 Add manifestflags class
Matt Mackall <mpm@selenic.com>
parents: 2470
diff changeset
   281
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   282
    def text(self, usemanifestv2=False):
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   283
        if usemanifestv2:
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   284
            return _textv2(self._lm.iterentries())
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   285
        else:
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   286
            # use (probably) native version for v1
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   287
            return self._lm.text()
22408
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   288
22931
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   289
    def fastdelta(self, base, changes):
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   290
        """Given a base manifest text as an array.array and a list of changes
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   291
        relative to that text, compute a delta that can be used by revlog.
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   292
        """
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   293
        delta = []
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   294
        dstart = None
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   295
        dend = None
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   296
        dline = [""]
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   297
        start = 0
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   298
        # zero copy representation of base as a buffer
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   299
        addbuf = util.buffer(base)
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   300
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   301
        # start with a readonly loop that finds the offset of
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   302
        # each line and creates the deltas
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   303
        for f, todelete in changes:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   304
            # bs will either be the index of the item or the insert point
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   305
            start, end = _msearch(addbuf, f, start)
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   306
            if not todelete:
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   307
                h, fl = self._lm[f]
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   308
                l = "%s\0%s%s\n" % (f, revlog.hex(h), fl)
22931
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   309
            else:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   310
                if start == end:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   311
                    # item we want to delete was not found, error out
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   312
                    raise AssertionError(
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   313
                            _("failed to remove %s from manifest") % f)
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   314
                l = ""
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   315
            if dstart is not None and dstart <= start and dend >= start:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   316
                if dend < end:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   317
                    dend = end
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   318
                if l:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   319
                    dline.append(l)
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   320
            else:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   321
                if dstart is not None:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   322
                    delta.append([dstart, dend, "".join(dline)])
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   323
                dstart = start
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   324
                dend = end
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   325
                dline = [l]
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   326
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   327
        if dstart is not None:
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   328
            delta.append([dstart, dend, "".join(dline)])
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   329
        # apply the delta to the base, and get a delta for addrevision
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   330
        deltatext, arraytext = _addlistdelta(base, delta)
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   331
        return arraytext, deltatext
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   332
22930
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   333
def _msearch(m, s, lo=0, hi=None):
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   334
    '''return a tuple (start, end) that says where to find s within m.
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   335
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   336
    If the string is found m[start:end] are the line containing
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   337
    that string.  If start == end the string was not found and
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   338
    they indicate the proper sorted insertion point.
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   339
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   340
    m should be a buffer or a string
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   341
    s is a string'''
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   342
    def advance(i, c):
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   343
        while i < lenm and m[i] != c:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   344
            i += 1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   345
        return i
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   346
    if not s:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   347
        return (lo, lo)
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   348
    lenm = len(m)
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   349
    if not hi:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   350
        hi = lenm
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   351
    while lo < hi:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   352
        mid = (lo + hi) // 2
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   353
        start = mid
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   354
        while start > 0 and m[start - 1] != '\n':
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   355
            start -= 1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   356
        end = advance(start, '\0')
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   357
        if m[start:end] < s:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   358
            # we know that after the null there are 40 bytes of sha1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   359
            # this translates to the bisect lo = mid + 1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   360
            lo = advance(end + 40, '\n') + 1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   361
        else:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   362
            # this translates to the bisect hi = mid
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   363
            hi = start
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   364
    end = advance(lo, '\0')
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   365
    found = m[lo:end]
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   366
    if s == found:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   367
        # we know that after the null there are 40 bytes of sha1
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   368
        end = advance(end + 40, '\n')
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   369
        return (lo, end + 1)
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   370
    else:
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   371
        return (lo, lo)
1acb81d10eaf manifest: move _search to module level and rename to _msearch
Augie Fackler <raf@durin42.com>
parents: 22929
diff changeset
   372
22415
65ec6c5c0fb3 manifest: mark addlistdelta and checkforbidden as module-private
Augie Fackler <raf@durin42.com>
parents: 22409
diff changeset
   373
def _checkforbidden(l):
22408
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   374
    """Check filenames for illegal characters."""
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   375
    for f in l:
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   376
        if '\n' in f or '\r' in f:
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   377
            raise error.RevlogError(
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   378
                _("'\\n' and '\\r' disallowed in filenames: %r") % f)
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   379
dc97e04c12ad manifest: move checkforbidden to module-level
Augie Fackler <raf@durin42.com>
parents: 21879
diff changeset
   380
22409
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   381
# apply the changes collected during the bisect loop to our addlist
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   382
# return a delta suitable for addrevision
22415
65ec6c5c0fb3 manifest: mark addlistdelta and checkforbidden as module-private
Augie Fackler <raf@durin42.com>
parents: 22409
diff changeset
   383
def _addlistdelta(addlist, x):
22409
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   384
    # for large addlist arrays, building a new array is cheaper
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   385
    # than repeatedly modifying the existing one
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   386
    currentposition = 0
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   387
    newaddlist = array.array('c')
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   388
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   389
    for start, end, content in x:
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   390
        newaddlist += addlist[currentposition:start]
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   391
        if content:
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   392
            newaddlist += array.array('c', content)
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   393
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   394
        currentposition = end
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   395
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   396
    newaddlist += addlist[currentposition:]
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   397
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   398
    deltatext = "".join(struct.pack(">lll", start, end, len(content))
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   399
                   + content for start, end, content in x)
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   400
    return deltatext, newaddlist
8f09b785b59b manifest: move addlistdelta to module-level
Augie Fackler <raf@durin42.com>
parents: 22408
diff changeset
   401
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   402
def _splittopdir(f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   403
    if '/' in f:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   404
        dir, subpath = f.split('/', 1)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   405
        return dir + '/', subpath
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   406
    else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   407
        return '', f
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   408
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   409
class treemanifest(object):
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   410
    def __init__(self, dir='', text=''):
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   411
        self._dir = dir
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   412
        self._dirs = {}
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   413
        # Using _lazymanifest here is a little slower than plain old dicts
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   414
        self._files = {}
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   415
        self._flags = {}
24524
63b6031384fc manifest: extract method for parsing manifest
Martin von Zweigbergk <martinvonz@google.com>
parents: 24502
diff changeset
   416
        for f, n, fl in _parse(text):
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   417
            self[f] = n
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   418
            if fl:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   419
                self.setflag(f, fl)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   420
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   421
    def _subpath(self, path):
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   422
        return self._dir + path
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   423
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   424
    def __len__(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   425
        size = len(self._files)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   426
        for m in self._dirs.values():
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   427
            size += m.__len__()
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   428
        return size
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   429
24551
4fdf5eac5b39 treemanifest: add treemanifest._isempty()
Drew Gottlieb <drgott@google.com>
parents: 24550
diff changeset
   430
    def _isempty(self):
4fdf5eac5b39 treemanifest: add treemanifest._isempty()
Drew Gottlieb <drgott@google.com>
parents: 24550
diff changeset
   431
        return (not self._files and (not self._dirs or
4fdf5eac5b39 treemanifest: add treemanifest._isempty()
Drew Gottlieb <drgott@google.com>
parents: 24550
diff changeset
   432
                util.all(m._isempty() for m in self._dirs.values())))
4fdf5eac5b39 treemanifest: add treemanifest._isempty()
Drew Gottlieb <drgott@google.com>
parents: 24550
diff changeset
   433
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   434
    def __str__(self):
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   435
        return '<treemanifest dir=%s>' % self._dir
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   436
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   437
    def iteritems(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   438
        for p, n in sorted(self._dirs.items() + self._files.items()):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   439
            if p in self._files:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   440
                yield self._subpath(p), n
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   441
            else:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   442
                for f, sn in n.iteritems():
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   443
                    yield f, sn
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   444
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   445
    def iterkeys(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   446
        for p in sorted(self._dirs.keys() + self._files.keys()):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   447
            if p in self._files:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   448
                yield self._subpath(p)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   449
            else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   450
                for f in self._dirs[p].iterkeys():
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   451
                    yield f
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   452
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   453
    def keys(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   454
        return list(self.iterkeys())
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   455
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   456
    def __iter__(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   457
        return self.iterkeys()
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   458
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   459
    def __contains__(self, f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   460
        if f is None:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   461
            return False
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   462
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   463
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   464
            if dir not in self._dirs:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   465
                return False
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   466
            return self._dirs[dir].__contains__(subpath)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   467
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   468
            return f in self._files
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   469
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   470
    def get(self, f, default=None):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   471
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   472
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   473
            if dir not in self._dirs:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   474
                return default
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   475
            return self._dirs[dir].get(subpath, default)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   476
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   477
            return self._files.get(f, default)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   478
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   479
    def __getitem__(self, f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   480
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   481
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   482
            return self._dirs[dir].__getitem__(subpath)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   483
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   484
            return self._files[f]
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   485
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   486
    def flags(self, f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   487
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   488
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   489
            if dir not in self._dirs:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   490
                return ''
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   491
            return self._dirs[dir].flags(subpath)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   492
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   493
            if f in self._dirs:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   494
                return ''
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   495
            return self._flags.get(f, '')
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   496
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   497
    def find(self, f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   498
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   499
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   500
            return self._dirs[dir].find(subpath)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   501
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   502
            return self._files[f], self._flags.get(f, '')
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   503
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   504
    def __delitem__(self, f):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   505
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   506
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   507
            self._dirs[dir].__delitem__(subpath)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   508
            # If the directory is now empty, remove it
24551
4fdf5eac5b39 treemanifest: add treemanifest._isempty()
Drew Gottlieb <drgott@google.com>
parents: 24550
diff changeset
   509
            if self._dirs[dir]._isempty():
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   510
                del self._dirs[dir]
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   511
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   512
            del self._files[f]
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   513
            if f in self._flags:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   514
                del self._flags[f]
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   515
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   516
    def __setitem__(self, f, n):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   517
        assert n is not None
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   518
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   519
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   520
            if dir not in self._dirs:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   521
                self._dirs[dir] = treemanifest(self._subpath(dir))
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   522
            self._dirs[dir].__setitem__(subpath, n)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   523
        else:
24467
bfb754050ccd treemanifest: drop 22nd byte for consistency with manifestdict
Martin von Zweigbergk <martinvonz@google.com>
parents: 24448
diff changeset
   524
            self._files[f] = n[:21] # to match manifestdict's behavior
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   525
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   526
    def setflag(self, f, flags):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   527
        """Set the flags (symlink, executable) for path f."""
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   528
        dir, subpath = _splittopdir(f)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   529
        if dir:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   530
            if dir not in self._dirs:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   531
                self._dirs[dir] = treemanifest(self._subpath(dir))
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   532
            self._dirs[dir].setflag(subpath, flags)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   533
        else:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   534
            self._flags[f] = flags
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   535
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   536
    def copy(self):
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   537
        copy = treemanifest(self._dir)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   538
        for d in self._dirs:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   539
            copy._dirs[d] = self._dirs[d].copy()
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   540
        copy._files = dict.copy(self._files)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   541
        copy._flags = dict.copy(self._flags)
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   542
        return copy
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   543
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   544
    def filesnotin(self, m2):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   545
        '''Set of files in this manifest that are not in the other'''
24405
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   546
        files = set()
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   547
        def _filesnotin(t1, t2):
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   548
            for d, m1 in t1._dirs.iteritems():
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   549
                if d in t2._dirs:
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   550
                    m2 = t2._dirs[d]
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   551
                    _filesnotin(m1, m2)
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   552
                else:
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   553
                    files.update(m1.iterkeys())
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   554
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   555
            for fn in t1._files.iterkeys():
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   556
                if fn not in t2._files:
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   557
                    files.add(t1._subpath(fn))
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   558
cbe9d50d9e65 treemanifest: make filesnotin() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24404
diff changeset
   559
        _filesnotin(self, m2)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   560
        return files
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   561
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   562
    @propertycache
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   563
    def _alldirs(self):
24635
21e1ece30f8c util: move dirs() and finddirs() from scmutil to util
Drew Gottlieb <drgott@google.com>
parents: 24600
diff changeset
   564
        return util.dirs(self)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   565
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   566
    def dirs(self):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   567
        return self._alldirs
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   568
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   569
    def hasdir(self, dir):
24406
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   570
        topdir, subdir = _splittopdir(dir)
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   571
        if topdir:
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   572
            if topdir in self._dirs:
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   573
                return self._dirs[topdir].hasdir(subdir)
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   574
            return False
1297480ed347 treemanifest: make hasdir() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24405
diff changeset
   575
        return (dir + '/') in self._dirs
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   576
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   577
    def matches(self, match):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   578
        '''generate a new manifest filtered by the match argument'''
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   579
        if match.always():
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   580
            return self.copy()
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   581
24552
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   582
        return self._matches(match)
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   583
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   584
    def _matches(self, match, alldirs=False):
24552
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   585
        '''recursively generate a new manifest filtered by the match argument.
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   586
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   587
        Will visit all subdirectories if alldirs is True, otherwise it will
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   588
        only visit subdirectories for which match.visitdir is True.'''
24552
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   589
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   590
        ret = treemanifest(self._dir)
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   591
        if not alldirs:
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   592
            # substring to strip trailing slash
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   593
            visit = match.visitdir(self._dir[:-1] or '.')
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   594
            if not visit:
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   595
                return ret
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   596
            alldirs = (visit == 'all')
24552
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   597
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   598
        for fn in self._files:
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   599
            fullp = self._subpath(fn)
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   600
            if not match(fullp):
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   601
                continue
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   602
            ret._files[fn] = self._files[fn]
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   603
            if fn in self._flags:
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   604
                ret._flags[fn] = self._flags[fn]
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   605
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   606
        for dir, subm in self._dirs.iteritems():
24636
36872036169b treemanifest: further optimize treemanifest.matches()
Drew Gottlieb <drgott@google.com>
parents: 24635
diff changeset
   607
            m = subm._matches(match, alldirs)
24552
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   608
            if not m._isempty():
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   609
                ret._dirs[dir] = m
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   610
a2292da6d821 treemanifest: make treemanifest.matches() faster
Drew Gottlieb <drgott@google.com>
parents: 24551
diff changeset
   611
        return ret
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   612
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   613
    def diff(self, m2, clean=False):
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   614
        '''Finds changes between the current manifest and m2.
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   615
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   616
        Args:
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   617
          m2: the manifest to which this manifest should be compared.
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   618
          clean: if true, include files unchanged between these manifests
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   619
                 with a None value in the returned dictionary.
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   620
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   621
        The result is returned as a dict with filename as key and
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   622
        values of the form ((n1,fl1),(n2,fl2)), where n1/n2 is the
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   623
        nodeid in the current/other manifest and fl1/fl2 is the flag
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   624
        in the current/other manifest. Where the file does not exist,
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   625
        the nodeid will be None and the flags will be the empty
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   626
        string.
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   627
        '''
24404
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   628
        result = {}
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   629
        emptytree = treemanifest()
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   630
        def _diff(t1, t2):
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   631
            for d, m1 in t1._dirs.iteritems():
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   632
                m2 = t2._dirs.get(d, emptytree)
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   633
                _diff(m1, m2)
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   634
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   635
            for d, m2 in t2._dirs.iteritems():
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   636
                if d not in t1._dirs:
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   637
                    _diff(emptytree, m2)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   638
24404
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   639
            for fn, n1 in t1._files.iteritems():
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   640
                fl1 = t1._flags.get(fn, '')
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   641
                n2 = t2._files.get(fn, None)
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   642
                fl2 = t2._flags.get(fn, '')
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   643
                if n1 != n2 or fl1 != fl2:
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   644
                    result[t1._subpath(fn)] = ((n1, fl1), (n2, fl2))
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   645
                elif clean:
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   646
                    result[t1._subpath(fn)] = None
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   647
24404
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   648
            for fn, n2 in t2._files.iteritems():
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   649
                if fn not in t1._files:
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   650
                    fl2 = t2._flags.get(fn, '')
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   651
                    result[t2._subpath(fn)] = ((None, ''), (n2, fl2))
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   652
24404
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   653
        _diff(self, m2)
96cccf1e3257 treemanifest: make diff() faster
Martin von Zweigbergk <martinvonz@google.com>
parents: 24403
diff changeset
   654
        return result
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   655
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   656
    def text(self, usemanifestv2=False):
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   657
        """Get the full data of this manifest as a bytestring."""
24525
e118f74d246f manifest: extract method for creating manifest text
Martin von Zweigbergk <martinvonz@google.com>
parents: 24524
diff changeset
   658
        flags = self.flags
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   659
        return _text(((f, self[f], flags(f)) for f in self.keys()),
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   660
                     usemanifestv2)
24401
e6e023d57e94 treemanifest: create treemanifest class
Martin von Zweigbergk <martinvonz@google.com>
parents: 24396
diff changeset
   661
7634
14a4337a9b9b revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents: 7633
diff changeset
   662
class manifest(revlog.revlog):
4258
b11a2fb59cf5 revlog: simplify revlog version handling
Matt Mackall <mpm@selenic.com>
parents: 4257
diff changeset
   663
    def __init__(self, opener):
24033
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   664
        # During normal operations, we expect to deal with not more than four
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   665
        # revs at a time (such as during commit --amend). When rebasing large
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   666
        # stacks of commits, the number can go up, hence the config knob below.
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   667
        cachesize = 4
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   668
        usetreemanifest = False
24526
cd50f3717639 manifestv2: add (unused) config option
Martin von Zweigbergk <martinvonz@google.com>
parents: 24525
diff changeset
   669
        usemanifestv2 = False
24033
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   670
        opts = getattr(opener, 'options', None)
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   671
        if opts is not None:
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   672
            cachesize = opts.get('manifestcachesize', cachesize)
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   673
            usetreemanifest = opts.get('usetreemanifest', usetreemanifest)
24571
919f8ce040be manifestv2: set requires at repo creation time
Martin von Zweigbergk <martinvonz@google.com>
parents: 24552
diff changeset
   674
            usemanifestv2 = opts.get('manifestv2', usemanifestv2)
24033
ed5e8a9598ce manifest: make lru size configurable
Durham Goode <durham@fb.com>
parents: 23758
diff changeset
   675
        self._mancache = util.lrucachedict(cachesize)
7634
14a4337a9b9b revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents: 7633
diff changeset
   676
        revlog.revlog.__init__(self, opener, "00manifest.i")
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   677
        self._usetreemanifest = usetreemanifest
24526
cd50f3717639 manifestv2: add (unused) config option
Martin von Zweigbergk <martinvonz@google.com>
parents: 24525
diff changeset
   678
        self._usemanifestv2 = usemanifestv2
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   679
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   680
    def _newmanifest(self, data=''):
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   681
        if self._usetreemanifest:
24403
0e23faa1511c treemanifest: store directory path in treemanifest nodes
Martin von Zweigbergk <martinvonz@google.com>
parents: 24402
diff changeset
   682
            return treemanifest('', data)
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   683
        return manifestdict(data)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   684
24528
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   685
    def _slowreaddelta(self, node):
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   686
        r0 = self.deltaparent(self.rev(node))
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   687
        m0 = self.read(self.node(r0))
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   688
        m1 = self.read(node)
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   689
        md = self._newmanifest()
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   690
        for f, ((n0, fl0), (n1, fl1)) in m0.diff(m1).iteritems():
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   691
            if n1:
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   692
                md[f] = n1
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   693
                if fl1:
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   694
                    md.setflag(f, fl1)
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   695
        return md
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   696
3196
f3b939444c72 Abstract manifest block parsing.
Brendan Cully <brendan@kublai.com>
parents: 3148
diff changeset
   697
    def readdelta(self, node):
24600
ea24cf92557a treemanifest: disable readdelta optimization
Martin von Zweigbergk <martinvonz@google.com>
parents: 24573
diff changeset
   698
        if self._usemanifestv2 or self._usetreemanifest:
24528
b538ae24aa97 manifestv2: implement slow readdelta() without revdiff
Martin von Zweigbergk <martinvonz@google.com>
parents: 24527
diff changeset
   699
            return self._slowreaddelta(node)
7362
6db4a2ccef3a revlog: remove delta function
Matt Mackall <mpm@selenic.com>
parents: 6765
diff changeset
   700
        r = self.rev(node)
24224
d71837d06597 manifest: do parsing inside manifestdict contstructor
Augie Fackler <augie@google.com>
parents: 24223
diff changeset
   701
        d = mdiff.patchtext(self.revdiff(self.deltaparent(r), r))
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   702
        return self._newmanifest(d)
3223
53e843840349 Whitespace/Tab cleanup
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3196
diff changeset
   703
13711
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   704
    def readfast(self, node):
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   705
        '''use the faster of readdelta or read'''
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   706
        r = self.rev(node)
14208
d62d597b8974 revlog: compute correct deltaparent in the deltaparent function
Sune Foldager <cryo@cyanite.org>
parents: 13711
diff changeset
   707
        deltaparent = self.deltaparent(r)
d62d597b8974 revlog: compute correct deltaparent in the deltaparent function
Sune Foldager <cryo@cyanite.org>
parents: 13711
diff changeset
   708
        if deltaparent != revlog.nullrev and deltaparent in self.parentrevs(r):
13711
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   709
            return self.readdelta(node)
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   710
        return self.read(node)
ed913fd7837b manifest: add readfast method
Matt Mackall <mpm@selenic.com>
parents: 13031
diff changeset
   711
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   712
    def read(self, node):
7634
14a4337a9b9b revlog: kill from-style imports
Matt Mackall <mpm@selenic.com>
parents: 7633
diff changeset
   713
        if node == revlog.nullid:
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   714
            return self._newmanifest() # don't upset local cache
18604
a1141f04e368 manifest: use a size 3 LRU cache to store parsed manifests
Siddharth Agarwal <sid0@fb.com>
parents: 17983
diff changeset
   715
        if node in self._mancache:
a1141f04e368 manifest: use a size 3 LRU cache to store parsed manifests
Siddharth Agarwal <sid0@fb.com>
parents: 17983
diff changeset
   716
            return self._mancache[node][0]
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   717
        text = self.revision(node)
9414
65dc516363ee manifest: simplify cache handling, use a unique cache
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9413
diff changeset
   718
        arraytext = array.array('c', text)
24402
c2287f203ec4 treemanifest: add configuration for using treemanifest type
Martin von Zweigbergk <martinvonz@google.com>
parents: 24401
diff changeset
   719
        m = self._newmanifest(text)
24147
ba4fcd80079d manifest: rename 'mf', 'map', and 'mapping' to 'm'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24146
diff changeset
   720
        self._mancache[node] = (m, arraytext)
ba4fcd80079d manifest: rename 'mf', 'map', and 'mapping' to 'm'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24146
diff changeset
   721
        return m
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   722
2320
dbdce3b99988 fix parsing of tags. make parse errors useful. add new tag tests.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2142
diff changeset
   723
    def find(self, node, f):
dbdce3b99988 fix parsing of tags. make parse errors useful. add new tag tests.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2142
diff changeset
   724
        '''look up entry for a single file efficiently.
4159
a896607d3ec3 fix manifest.find
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 3891
diff changeset
   725
        return (node, flags) pair if found, (None, None) if not.'''
24292
b7add2ebef9e manifest: rewrite find(node, f) in terms of read(node)
Martin von Zweigbergk <martinvonz@google.com>
parents: 24277
diff changeset
   726
        m = self.read(node)
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   727
        try:
24292
b7add2ebef9e manifest: rewrite find(node, f) in terms of read(node)
Martin von Zweigbergk <martinvonz@google.com>
parents: 24277
diff changeset
   728
            return m.find(f)
24225
3e5c4af69808 manifest: split manifestdict into high-level and low-level logic
Augie Fackler <augie@google.com>
parents: 24224
diff changeset
   729
        except KeyError:
2320
dbdce3b99988 fix parsing of tags. make parse errors useful. add new tag tests.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2142
diff changeset
   730
            return None, None
dbdce3b99988 fix parsing of tags. make parse errors useful. add new tag tests.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2142
diff changeset
   731
24147
ba4fcd80079d manifest: rename 'mf', 'map', and 'mapping' to 'm'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24146
diff changeset
   732
    def add(self, m, transaction, link, p1, p2, added, removed):
24527
8aead3bc5ff8 manifestv2: disable fastdelta optimization
Martin von Zweigbergk <martinvonz@google.com>
parents: 24526
diff changeset
   733
        if (p1 in self._mancache and not self._usetreemanifest
8aead3bc5ff8 manifestv2: disable fastdelta optimization
Martin von Zweigbergk <martinvonz@google.com>
parents: 24526
diff changeset
   734
            and not self._usemanifestv2):
22788
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   735
            # If our first parent is in the manifest cache, we can
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   736
            # compute a delta here using properties we know about the
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   737
            # manifest up-front, which may save time later for the
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   738
            # revlog layer.
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   739
22415
65ec6c5c0fb3 manifest: mark addlistdelta and checkforbidden as module-private
Augie Fackler <raf@durin42.com>
parents: 22409
diff changeset
   740
            _checkforbidden(added)
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   741
            # combine the changed lists into one list for sorting
9415
e0cc9fa2a576 manifest.add(): cleanup worklist construction and iteration
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9414
diff changeset
   742
            work = [(x, False) for x in added]
e0cc9fa2a576 manifest.add(): cleanup worklist construction and iteration
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9414
diff changeset
   743
            work.extend((x, True) for x in removed)
17428
72803c8edaa4 avoid using abbreviations that look like spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents: 17426
diff changeset
   744
            # this could use heapq.merge() (from Python 2.6+) or equivalent
9415
e0cc9fa2a576 manifest.add(): cleanup worklist construction and iteration
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9414
diff changeset
   745
            # since the lists are already sorted
644
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   746
            work.sort()
6ebe118280bd Performance enhancements for manifest.add()
mason@suse.com
parents: 639
diff changeset
   747
24147
ba4fcd80079d manifest: rename 'mf', 'map', and 'mapping' to 'm'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24146
diff changeset
   748
            arraytext, deltatext = m.fastdelta(self._mancache[p1][1], work)
22931
48c0b101a9de manifest: add fastdelta method to manifestdict
Augie Fackler <raf@durin42.com>
parents: 22930
diff changeset
   749
            cachedelta = self.rev(p1), deltatext
15657
d976b1ef6760 util: don't mess with builtins to emulate buffer()
Matt Mackall <mpm@selenic.com>
parents: 14632
diff changeset
   750
            text = util.buffer(arraytext)
22788
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   751
        else:
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   752
            # The first parent manifest isn't already loaded, so we'll
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   753
            # just encode a fulltext of the manifest and pass that
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   754
            # through to the revlog layer, and let it handle the delta
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   755
            # process.
24573
701d3554de0e manifestv2: add support for writing new manifest format
Martin von Zweigbergk <martinvonz@google.com>
parents: 24572
diff changeset
   756
            text = m.text(self._usemanifestv2)
22788
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   757
            arraytext = array.array('c', text)
160efd225b24 manifest: rearrange add() method and add comments for clarity
Augie Fackler <raf@durin42.com>
parents: 22787
diff changeset
   758
            cachedelta = None
1534
80a3d6a0af71 Optimize manifest.add
mason@suse.com
parents: 1451
diff changeset
   759
9420
d0db168136dc manifest/revlog: do not let the revlog cache mutable objects
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 9416
diff changeset
   760
        n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
24147
ba4fcd80079d manifest: rename 'mf', 'map', and 'mapping' to 'm'
Martin von Zweigbergk <martinvonz@google.com>
parents: 24146
diff changeset
   761
        self._mancache[n] = (m, arraytext)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   762
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   763
        return n