diff -r 15dedc0c5c35 -r 308d9c245337 mercurial/helptext/internals/dirstate-v2.txt --- a/mercurial/helptext/internals/dirstate-v2.txt Wed Oct 13 16:21:39 2021 +0200 +++ b/mercurial/helptext/internals/dirstate-v2.txt Wed Oct 13 17:32:52 2021 +0200 @@ -372,7 +372,7 @@ This counter is used to implement `has_tracked_dir`. * Offset 30: - Some boolean values packed as bits of a single byte. + A single `flags` byte that packs some boolean values as bits. Starting from least-significant, bit masks are:: WDIR_TRACKED = 1 << 0 @@ -381,110 +381,116 @@ HAS_MODE_AND_SIZE = 1 << 3 HAS_MTIME = 1 << 4 MODE_EXEC_PERM = 1 << 5 - MODE_IS_SYMLINK = 1 << 7 - - - Other bits are unset. The meaning of these bits are: - - `WDIR_TRACKED` - Set if the working directory contains a tracked file at this node’s path. - This is typically set and unset by `hg add` and `hg rm`. - - `P1_TRACKED` - set if the working directory’s first parent changeset - (whose node identifier is found in tree metadata) - contains a tracked file at this node’s path. - This is a cache to reduce manifest lookups. - - `P2_INFO` - Set if the file has been involved in some merge operation. - Either because it was actually merged, - or because the version in the second parent p2 version was ahead, - or because some rename moved it there. - In either case `hg status` will want it displayed as modified. + MODE_IS_SYMLINK = 1 << 6 - Files that would be mentioned at all in the `dirstate-v1` file format - have a node with at least one of the above three bits set in `dirstate-v2`. - Let’s call these files "tracked anywhere", - and "untracked" the nodes with all three of these bits unset. - Untracked nodes are typically for directories: - they hold child nodes and form the tree structure. - Additional untracked nodes may also exist. - Although implementations should strive to clean up nodes - that are entirely unused, other untracked nodes may also exist. - For example, a future version of Mercurial might in some cases - add nodes for untracked files or/and ignored files in the working directory - in order to optimize `hg status` - by enabling it to skip `readdir` in more cases. + The meaning of each bit is described below. + Other bits are unset. - When a node is for a file tracked anywhere: - - If `HAS_MODE_AND_SIZE` is set, the file is expected - to be a symbolic link or a normal file based on `MODE_IS_SYMLINK`. - - If `HAS_MODE_AND_SIZE` is set, the file’s owner is expected - to have execute permission or not based on `MODE_EXEC_PERM`. - - If `HAS_MODE_AND_SIZE` is unset, - the expected type of file and permission are unknown. - The rest of the node data is three fields: - - * Offset 31: - 4 unused bytes, set to zero +* Offset 31: + A `size` field described below, as a 32-bit integer. + Unlike in dirstate-v1, negative values are not used. - * Offset 35: - If `HAS_MODE_AND_SIZE` is unset, four zero bytes. - Otherwise, a 32-bit integer for expected size of the file - truncated to its 31 least-significant bits. - Unlike in dirstate-v1, negative values are not used. - - * Offset 39: - If `HAS_MTIME` is unset, four zero bytes. - Otherwise, a 32-bit integer for expected modified time of the file - (as in `stat_result.st_mtime`), - truncated to its 31 least-significant bits. - Unlike in dirstate-v1, negative values are not used. - - If an untracked node `HAS_MTIME` *unset*, this space is unused: - - * Offset 31: - 12 unused bytes, set to zero - - If an untracked node `HAS_MTIME` *set*, - what follows is the modification time of a directory - represented similarly to the C `timespec` struct: - - * Offset 31: - 4 unused bytes, set to zero +* Offset 35: + The seconds component of an `mtime` field described below, + as a 32-bit integer. + Unlike in dirstate-v1, negative values are not used. - * Offset 35: - The number of seconds elapsed since the Unix epoch, - truncated to its lower 31 bits, - as a 32-bit integer. - - * Offset 39: - The sub-second number of nanoseconds elapsed since the Unix epoch, - as 32-bit integer. - Always greater than or equal to zero, and strictly less than a billion. - - The presence of a directory modification time means that at some point, - this path in the working directory was observed: - - - To be a directory - - With the given modification time - - That time was already strictly in the past when observed, - meaning that later changes cannot happen in the same clock tick - and must cause a different modification time - (unless the system clock jumps back and we get unlucky, - which is not impossible but deemed unlikely enough). - - All direct children of this directory - (as returned by `std::fs::read_dir`) - either have a corresponding dirstate node, - or are ignored by ignore patterns whose hash is in tree metadata. - - This means that if `std::fs::symlink_metadata` later reports - the same modification time - and ignored patterns haven’t changed, - a run of status that is not listing ignored files - can skip calling `std::fs::read_dir` again for this directory, - and iterate child dirstate nodes instead. - +* Offset 39: + The nanoseconds component of an `mtime` field described below, + as a 32-bit integer. * (Offset 43: end of this node) + +The meaning of the boolean values packed in `flags` is: + +`WDIR_TRACKED` + Set if the working directory contains a tracked file at this node’s path. + This is typically set and unset by `hg add` and `hg rm`. + +`P1_TRACKED` + Set if the working directory’s first parent changeset + (whose node identifier is found in tree metadata) + contains a tracked file at this node’s path. + This is a cache to reduce manifest lookups. + +`P2_INFO` + Set if the file has been involved in some merge operation. + Either because it was actually merged, + or because the version in the second parent p2 version was ahead, + or because some rename moved it there. + In either case `hg status` will want it displayed as modified. + +Files that would be mentioned at all in the `dirstate-v1` file format +have a node with at least one of the above three bits set in `dirstate-v2`. +Let’s call these files "tracked anywhere", +and "untracked" the nodes with all three of these bits unset. +Untracked nodes are typically for directories: +they hold child nodes and form the tree structure. +Additional untracked nodes may also exist. +Although implementations should strive to clean up nodes +that are entirely unused, other untracked nodes may also exist. +For example, a future version of Mercurial might in some cases +add nodes for untracked files or/and ignored files in the working directory +in order to optimize `hg status` +by enabling it to skip `readdir` in more cases. + +`HAS_MODE_AND_SIZE` + Must be unset for untracked nodes. + For files tracked anywhere, if this is set: + - The `size` field is the expected file size, + in bytes truncated its lower to 31 bits, + for the file to be clean. + - The expected execute permission for the file’s owner + is given by `MODE_EXEC_PERM` + - The expected file type is given by `MODE_IS_SIMLINK`: + a symbolic link if set, or a normal file if unset. + If this is unset the expected size, permission, and file type are unknown. + The `size` field is unused (set to zero). + +`HAS_MTIME` + If unset, the `mtime` field is unused (set to zero). + If set, it contains a timestamp represented as + - the number of seconds since the Unix epoch, + truncated to its lower 31 bits. + - and the number of nanoseconds since `mtime.seconds`, + always stritctly less than one billion. + This may be zero if more precision is not available. + (This can happen because of limitations in any of Mercurial, Python, + libc, the operating system, …) + + If set for a file tracked anywhere, + `mtime` is the expected modification time for the file to be clean. + + If set for an untracked node, at some point, + this path in the working directory was observed: + + - To be a directory + - With the modification time given in `mtime` + - That time was already strictly in the past when observed, + meaning that later changes cannot happen in the same clock tick + and must cause a different modification time + (unless the system clock jumps back and we get unlucky, + which is not impossible but deemed unlikely enough). + - All direct children of this directory + (as returned by `std::fs::read_dir`) + either have a corresponding dirstate node, + or are ignored by ignore patterns whose hash is in tree metadata. + + This means that if `std::fs::symlink_metadata` later reports + the same modification time + and ignored patterns haven’t changed, + a run of status that is not listing ignored files + can skip calling `std::fs::read_dir` again for this directory, + and iterate child dirstate nodes instead. + +`MODE_EXEC_PERM` + Must be unset if `HAS_MODE_AND_SIZE` is unset. + If `HAS_MODE_AND_SIZE` is set, + this indicates whether the file’s own is expected + to have execute permission. + +`MODE_IS_SYMLINK` + Must be unset if `HAS_MODE_AND_SIZE` is unset. + If `HAS_MODE_AND_SIZE` is set, + this indicates whether the file is expected to be a symlink + as opposed to a normal file.