mercurial/loggingutil.py
author Martin von Zweigbergk <martinvonz@google.com>
Thu, 04 Mar 2021 16:06:55 -0800
changeset 46634 ad30b29bc23d
parent 43077 687b865b95ad
child 46892 4a6024b87dfc
permissions -rw-r--r--
copies: choose target directory based on longest match If one side of a merge renames `dir1/` to `dir2/` and the subdirectory `dir1/subdir1/` to `dir2/subdir2/`, and the other side of the merge adds a file in `dir1/subdir1/`, we should clearly move that into `dir2/subdir2/`. We already detect the directories correctly before this patch, but we iterate over them in arbitrary order. That results in the new file sometimes ending up in `dir2/subdir1/` instead. This patch fixes it by iterating over the source directories by visiting subdirectories first. That's achieved by simply iterating over them in reverse lexicographical order. Without the fix, the test case still passes on Python 2 but fails on Python 3. It depends on the iteration order of the dict. I did not look into how it's built up and why it behaved differently before the fix. I could probably have gotten it to fail on Python 2 as well by choosing different directory names. Differential Revision: https://phab.mercurial-scm.org/D10115
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40799
03127e580980 loggingutil: extract openlogfile() and proxylogger to new module
Yuya Nishihara <yuya@tcha.org>
parents: 40798
diff changeset
     1
# loggingutil.py - utility for logging events
18669
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     2
#
18676
1506eb487ddd blackbox: fix copyright
Bryan O'Sullivan <bryano@fb.com>
parents: 18675
diff changeset
     3
# Copyright 2010 Nicolas Dumazet
18669
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     4
# Copyright 2013 Facebook, Inc.
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     5
#
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     6
# This software may be used and distributed according to the terms of the
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     7
# GNU General Public License version 2 or any later version.
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
     8
28090
8113c88b8e6d blackbox: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28027
diff changeset
     9
from __future__ import absolute_import
8113c88b8e6d blackbox: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28027
diff changeset
    10
8113c88b8e6d blackbox: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28027
diff changeset
    11
import errno
8113c88b8e6d blackbox: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28027
diff changeset
    12
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    13
from . import pycompat
18669
18242716a014 blackbox: adds a blackbox extension
Durham Goode <durham@fb.com>
parents:
diff changeset
    14
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    15
from .utils import (
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    16
    dateutil,
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    17
    procutil,
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    18
    stringutil,
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    19
)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    20
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    21
40799
03127e580980 loggingutil: extract openlogfile() and proxylogger to new module
Yuya Nishihara <yuya@tcha.org>
parents: 40798
diff changeset
    22
def openlogfile(ui, vfs, name, maxfiles=0, maxsize=0):
40800
698477777883 loggingutil: document openlogfile()
Yuya Nishihara <yuya@tcha.org>
parents: 40799
diff changeset
    23
    """Open log file in append mode, with optional rotation
698477777883 loggingutil: document openlogfile()
Yuya Nishihara <yuya@tcha.org>
parents: 40799
diff changeset
    24
698477777883 loggingutil: document openlogfile()
Yuya Nishihara <yuya@tcha.org>
parents: 40799
diff changeset
    25
    If maxsize > 0, the log file will be rotated up to maxfiles.
698477777883 loggingutil: document openlogfile()
Yuya Nishihara <yuya@tcha.org>
parents: 40799
diff changeset
    26
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    27
34300
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    28
    def rotate(oldpath, newpath):
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    29
        try:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    30
            vfs.unlink(newpath)
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    31
        except OSError as err:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    32
            if err.errno != errno.ENOENT:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    33
                ui.debug(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    34
                    b"warning: cannot remove '%s': %s\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    35
                    % (newpath, err.strerror)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    36
                )
34300
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    37
        try:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    38
            if newpath:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    39
                vfs.rename(oldpath, newpath)
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    40
        except OSError as err:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    41
            if err.errno != errno.ENOENT:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    42
                ui.debug(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    43
                    b"warning: cannot rename '%s' to '%s': %s\n"
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    44
                    % (newpath, oldpath, err.strerror)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    45
                )
34300
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    46
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    47
    if maxsize > 0:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    48
        try:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    49
            st = vfs.stat(name)
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    50
        except OSError:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    51
            pass
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    52
        else:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    53
            if st.st_size >= maxsize:
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    54
                path = vfs.join(name)
38783
e7aa113b14f7 global: use pycompat.xrange()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37120
diff changeset
    55
                for i in pycompat.xrange(maxfiles - 1, 1, -1):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    56
                    rotate(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    57
                        oldpath=b'%s.%d' % (path, i - 1),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    58
                        newpath=b'%s.%d' % (path, i),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    59
                    )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    60
                rotate(oldpath=path, newpath=maxfiles > 0 and path + b'.1')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    61
    return vfs(name, b'a', makeparentdirs=False)
34300
e6723c939344 blackbox: move _openlogfile to a separate method
Jun Wu <quark@fb.com>
parents: 34299
diff changeset
    62
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    63
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    64
def _formatlogline(msg):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    65
    date = dateutil.datestr(format=b'%Y/%m/%d %H:%M:%S')
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    66
    pid = procutil.getpid()
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    67
    return b'%s (%d)> %s' % (date, pid, msg)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    68
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    69
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    70
def _matchevent(event, tracked):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    71
    return b'*' in tracked or event in tracked
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    72
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    73
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    74
class filelogger(object):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    75
    """Basic logger backed by physical file with optional rotation"""
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    76
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    77
    def __init__(self, vfs, name, tracked, maxfiles=0, maxsize=0):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    78
        self._vfs = vfs
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    79
        self._name = name
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    80
        self._trackedevents = set(tracked)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    81
        self._maxfiles = maxfiles
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    82
        self._maxsize = maxsize
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    83
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    84
    def tracked(self, event):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    85
        return _matchevent(event, self._trackedevents)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    86
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    87
    def log(self, ui, event, msg, opts):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    88
        line = _formatlogline(msg)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    89
        try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    90
            with openlogfile(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    91
                ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    92
                self._vfs,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    93
                self._name,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    94
                maxfiles=self._maxfiles,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    95
                maxsize=self._maxsize,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    96
            ) as fp:
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    97
                fp.write(line)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
    98
        except IOError as err:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
    99
            ui.debug(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   100
                b'cannot write to %s: %s\n'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   101
                % (self._name, stringutil.forcebytestr(err))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   102
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   103
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   104
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   105
class fileobjectlogger(object):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   106
    """Basic logger backed by file-like object"""
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   107
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   108
    def __init__(self, fp, tracked):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   109
        self._fp = fp
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   110
        self._trackedevents = set(tracked)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   111
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   112
    def tracked(self, event):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   113
        return _matchevent(event, self._trackedevents)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   114
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   115
    def log(self, ui, event, msg, opts):
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   116
        line = _formatlogline(msg)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   117
        try:
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   118
            self._fp.write(line)
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   119
            self._fp.flush()
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   120
        except IOError as err:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   121
            ui.debug(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   122
                b'cannot write to %s: %s\n'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   123
                % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   124
                    stringutil.forcebytestr(self._fp.name),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   125
                    stringutil.forcebytestr(err),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   126
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   127
            )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 40821
diff changeset
   128
40821
96be0ecad648 loggingutil: add basic logger backends
Yuya Nishihara <yuya@tcha.org>
parents: 40800
diff changeset
   129
40762
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   130
class proxylogger(object):
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   131
    """Forward log events to another logger to be set later"""
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   132
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   133
    def __init__(self):
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   134
        self.logger = None
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   135
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   136
    def tracked(self, event):
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   137
        return self.logger is not None and self.logger.tracked(event)
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   138
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   139
    def log(self, ui, event, msg, opts):
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   140
        assert self.logger is not None
37d6ee46a965 blackbox: extract global last logger to proxylogger class
Yuya Nishihara <yuya@tcha.org>
parents: 40760
diff changeset
   141
        self.logger.log(ui, event, msg, opts)