mercurial/utils/resourceutil.py
author Arseniy Alekseyev <aalekseyev@janestreet.com>
Fri, 26 Apr 2024 19:10:35 +0100
changeset 51626 865efc020c33
parent 50928 d718eddf01d9
permissions -rw-r--r--
dirstate: remove the python-side whitelist of allowed matchers This whitelist is too permissive because it allows matchers that contain disallowed ones deep inside, for example through `intersectionmatcher`. It is also too restrictive because it doesn't pass through some of the matchers we support, such as `patternmatcher`. It's also unnecessary because unsupported matchers raise `FallbackError` and we fall back anyway. Making this change makes more of the tests use rust code path, and therefore subtly change behavior. For example, rust status in largefiles repos seems to have strange behavior.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
     1
# resourceutil.py - utility for looking up resources
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     2
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     3
#  Copyright 2005 K. Thananchayan <thananck@yahoo.com>
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46783
diff changeset
     4
#  Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     5
#  Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     6
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     7
# 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: 9996
diff changeset
     8
# GNU General Public License version 2 or any later version.
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     9
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
    10
50756
847f703a4d13 utils: imp module is removed in Python 3.12 - get is_frozen() from _imp
Mads Kiilerich <mads@kiilerich.com>
parents: 49943
diff changeset
    11
import _imp
43672
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    12
import os
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
    13
import sys
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
    14
43671
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43657
diff changeset
    15
from .. import pycompat
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    16
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
    17
14228
116de1da2154 rename util.main_is_frozen to mainfrozen
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
    18
def mainfrozen():
6499
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    19
    """return True if we are a frozen executable.
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    20
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    21
    The code supports py2exe (most common, Windows only) and tools/freeze
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    22
    (portable, not much used).
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    23
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43019
diff changeset
    24
    return (
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50756
diff changeset
    25
        hasattr(sys, "frozen")  # new py2exe
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50756
diff changeset
    26
        or hasattr(sys, "importers")  # old py2exe
50756
847f703a4d13 utils: imp module is removed in Python 3.12 - get is_frozen() from _imp
Mads Kiilerich <mads@kiilerich.com>
parents: 49943
diff changeset
    27
        or _imp.is_frozen("__main__")  # tools/freeze
44924
6c8384afbf77 resourceutil: fix location of line comments
Manuel Jacob <me@manueljacob.de>
parents: 44241
diff changeset
    28
    )
43672
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    29
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    30
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    31
# the location of data files matching the source code
44241
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    32
if mainfrozen() and getattr(sys, "frozen", None) != "macosx_app":
43672
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    33
    # executable version (py2exe) doesn't support __file__
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    34
    datapath = os.path.dirname(pycompat.sysexecutable)
44208
9e367157a990 resourceutil: correct the root path for file based lookup under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44152
diff changeset
    35
    _rootpath = datapath
44219
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    36
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    37
    # The installers store the files outside of library.zip, like
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    38
    # C:\Program Files\Mercurial\defaultrc\*.rc.  This strips the
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    39
    # leading "mercurial." off of the package name, so that these
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    40
    # pseudo resources are found in their directory next to the
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    41
    # executable.
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    42
    def _package_path(package):
44241
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    43
        dirs = package.split(b".")
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    44
        assert dirs[0] == b"mercurial"
44219
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    45
        return os.path.join(_rootpath, *dirs[1:])
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    46
44241
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    47
43672
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    48
else:
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43671
diff changeset
    49
    datapath = os.path.dirname(os.path.dirname(pycompat.fsencode(__file__)))
44027
52f0140c2604 resourceutil: don't limit resources to the `mercurial` package
Matt Harbison <matt_harbison@yahoo.com>
parents: 43955
diff changeset
    50
    _rootpath = os.path.dirname(datapath)
43871
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    51
44219
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    52
    def _package_path(package):
44241
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    53
        return os.path.join(_rootpath, *package.split(b"."))
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    54
44219
aab70b540d3d resourceutil: account for the non-resource-like file hierarchy under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44208
diff changeset
    55
43871
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    56
try:
45452
dd9e28612468 resourceutil: document when we expect to take the importlib.resouces code path
Martin von Zweigbergk <martinvonz@google.com>
parents: 44924
diff changeset
    57
    # importlib.resources exists from Python 3.7; see fallback in except clause
dd9e28612468 resourceutil: document when we expect to take the importlib.resouces code path
Martin von Zweigbergk <martinvonz@google.com>
parents: 44924
diff changeset
    58
    # further down
48008
c0588d389c5f typing: suppress an import-error warning in `mercurial/utils/resourceutil.py`
Matt Harbison <matt_harbison@yahoo.com>
parents: 47860
diff changeset
    59
    from importlib import resources  # pytype: disable=import-error
43871
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    60
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    61
    # Force loading of the resources module
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50756
diff changeset
    62
    if hasattr(resources, 'files'):
49943
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
    63
        resources.files  # pytype: disable=module-attr
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
    64
    else:
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
    65
        resources.open_binary  # pytype: disable=module-attr
43871
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    66
49074
4ba27acdea63 resourceutil: force filesystem access to resources when using py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
    67
    # py2exe raises an AssertionError if uses importlib.resources
4ba27acdea63 resourceutil: force filesystem access to resources when using py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
    68
    if getattr(sys, "frozen", None) in ("console_exe", "windows_exe"):
4ba27acdea63 resourceutil: force filesystem access to resources when using py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
    69
        raise ImportError
4ba27acdea63 resourceutil: force filesystem access to resources when using py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
    70
43955
75ec46c63657 resourceutil: use `from importlib import resources`
Martin von Zweigbergk <martinvonz@google.com>
parents: 43905
diff changeset
    71
except (ImportError, AttributeError):
45452
dd9e28612468 resourceutil: document when we expect to take the importlib.resouces code path
Martin von Zweigbergk <martinvonz@google.com>
parents: 44924
diff changeset
    72
    # importlib.resources was not found (almost definitely because we're on a
dd9e28612468 resourceutil: document when we expect to take the importlib.resouces code path
Martin von Zweigbergk <martinvonz@google.com>
parents: 44924
diff changeset
    73
    # Python version before 3.7)
43871
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    74
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    75
    def open_resource(package, name):
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43862
diff changeset
    76
        path = os.path.join(_package_path(package), name)
44241
aea79f41ee55 resourceutil: blacken
Augie Fackler <augie@google.com>
parents: 44219
diff changeset
    77
        return open(path, "rb")
44028
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    78
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    79
    def is_resource(package, name):
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    80
        path = os.path.join(_package_path(package), name)
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    81
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    82
        try:
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    83
            return os.path.isfile(pycompat.fsdecode(path))
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    84
        except (IOError, OSError):
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44027
diff changeset
    85
            return False
44029
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    86
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    87
    def contents(package):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    88
        path = pycompat.fsdecode(_package_path(package))
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    89
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    90
        for p in os.listdir(path):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44028
diff changeset
    91
            yield pycompat.fsencode(p)
47860
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    92
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    93
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    94
else:
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    95
    from .. import encoding
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    96
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
    97
    def open_resource(package, name):
50928
d718eddf01d9 safehasattr: drop usage in favor of hasattr
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 50756
diff changeset
    98
        if hasattr(resources, 'files'):
49943
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
    99
            return (
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   100
                resources.files(  # pytype: disable=module-attr
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   101
                    pycompat.sysstr(package)
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   102
                )
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   103
                .joinpath(pycompat.sysstr(name))
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   104
                .open('rb')
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   105
            )
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   106
        else:
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   107
            return resources.open_binary(  # pytype: disable=module-attr
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   108
                pycompat.sysstr(package), pycompat.sysstr(name)
330d88217b83 resourceutil: start using importlib.resources.files() when possible
Anton Shestakov <av6@dwimlabs.net>
parents: 49074
diff changeset
   109
            )
47860
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   110
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   111
    def is_resource(package, name):
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   112
        return resources.is_resource(  # pytype: disable=module-attr
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   113
            pycompat.sysstr(package), encoding.strfromlocal(name)
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   114
        )
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   115
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   116
    def contents(package):
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   117
        # pytype: disable=module-attr
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   118
        for r in resources.contents(pycompat.sysstr(package)):
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   119
            # pytype: enable=module-attr
08f16b3331df resources: narrow the try:except clause to minimum
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 47858
diff changeset
   120
            yield encoding.strtolocal(r)