view mercurial/dirstateutils/timestamp.py @ 48674:f7086f6173f8 stable

dirstate-v2: rename the configuration to enable the format The rename of the old experimental name was overlooked before the 6.0 release. We rename everything to use the new name (and keep the released name as an alias for compatibility). Differential Revision: https://phab.mercurial-scm.org/D12129
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 01 Feb 2022 16:36:20 +0100
parents 83d0bd45b662
children 08b060abd658
line wrap: on
line source

# Copyright Mercurial Contributors
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

import functools
import stat


rangemask = 0x7FFFFFFF


@functools.total_ordering
class timestamp(tuple):
    """
    A Unix timestamp with optional nanoseconds precision,
    modulo 2**31 seconds.

    A 2-tuple containing:

    `truncated_seconds`: seconds since the Unix epoch,
    truncated to its lower 31 bits

    `subsecond_nanoseconds`: number of nanoseconds since `truncated_seconds`.
    When this is zero, the sub-second precision is considered unknown.
    """

    def __new__(cls, value):
        truncated_seconds, subsec_nanos = value
        value = (truncated_seconds & rangemask, subsec_nanos)
        return super(timestamp, cls).__new__(cls, value)

    def __eq__(self, other):
        self_secs, self_subsec_nanos = self
        other_secs, other_subsec_nanos = other
        return self_secs == other_secs and (
            self_subsec_nanos == other_subsec_nanos
            or self_subsec_nanos == 0
            or other_subsec_nanos == 0
        )

    def __gt__(self, other):
        self_secs, self_subsec_nanos = self
        other_secs, other_subsec_nanos = other
        if self_secs > other_secs:
            return True
        if self_secs < other_secs:
            return False
        if self_subsec_nanos == 0 or other_subsec_nanos == 0:
            # they are considered equal, so not "greater than"
            return False
        return self_subsec_nanos > other_subsec_nanos


def zero():
    """
    Returns the `timestamp` at the Unix epoch.
    """
    return tuple.__new__(timestamp, (0, 0))


def mtime_of(stat_result):
    """
    Takes an `os.stat_result`-like object and returns a `timestamp` object
    for its modification time.
    """
    try:
        # TODO: add this attribute to `osutil.stat` objects,
        # see `mercurial/cext/osutil.c`.
        #
        # This attribute is also not available on Python 2.
        nanos = stat_result.st_mtime_ns
    except AttributeError:
        # https://docs.python.org/2/library/os.html#os.stat_float_times
        # "For compatibility with older Python versions,
        #  accessing stat_result as a tuple always returns integers."
        secs = stat_result[stat.ST_MTIME]

        subsec_nanos = 0
    else:
        billion = int(1e9)
        secs = nanos // billion
        subsec_nanos = nanos % billion

    return timestamp((secs, subsec_nanos))