rust/hg-core/src/dirstate/entry.rs
changeset 48482 112184713852
parent 48468 000130cfafb6
child 49108 362312d61020
equal deleted inserted replaced
48481:c8ca21962ff4 48482:112184713852
    85         } else {
    85         } else {
    86             Err(DirstateV2ParseError)
    86             Err(DirstateV2ParseError)
    87         }
    87         }
    88     }
    88     }
    89 
    89 
       
    90     /// Returns a `TruncatedTimestamp` for the modification time of `metadata`.
       
    91     ///
       
    92     /// Propagates errors from `std` on platforms where modification time
       
    93     /// is not available at all.
    90     pub fn for_mtime_of(metadata: &fs::Metadata) -> io::Result<Self> {
    94     pub fn for_mtime_of(metadata: &fs::Metadata) -> io::Result<Self> {
    91         #[cfg(unix)]
    95         #[cfg(unix)]
    92         {
    96         {
    93             use std::os::unix::fs::MetadataExt;
    97             use std::os::unix::fs::MetadataExt;
    94             let seconds = metadata.mtime();
    98             let seconds = metadata.mtime();
   100         {
   104         {
   101             metadata.modified().map(Self::from)
   105             metadata.modified().map(Self::from)
   102         }
   106         }
   103     }
   107     }
   104 
   108 
   105     /// Returns whether this timestamp is reliable as the "mtime" of a file.
   109     /// Like `for_mtime_of`, but may return `None` or a value with
       
   110     /// `second_ambiguous` set if the mtime is not "reliable".
   106     ///
   111     ///
   107     /// A modification time is reliable if it is older than `boundary` (or
   112     /// A modification time is reliable if it is older than `boundary` (or
   108     /// sufficiently in the future).
   113     /// sufficiently in the future).
   109     ///
   114     ///
   110     /// Otherwise a concurrent modification might happens with the same mtime.
   115     /// Otherwise a concurrent modification might happens with the same mtime.
   111     pub fn is_reliable_mtime(&self, boundary: &Self) -> bool {
   116     pub fn for_reliable_mtime_of(
       
   117         metadata: &fs::Metadata,
       
   118         boundary: &Self,
       
   119     ) -> io::Result<Option<Self>> {
       
   120         let mut mtime = Self::for_mtime_of(metadata)?;
   112         // If the mtime of the ambiguous file is younger (or equal) to the
   121         // If the mtime of the ambiguous file is younger (or equal) to the
   113         // starting point of the `status` walk, we cannot garantee that
   122         // starting point of the `status` walk, we cannot garantee that
   114         // another, racy, write will not happen right after with the same mtime
   123         // another, racy, write will not happen right after with the same mtime
   115         // and we cannot cache the information.
   124         // and we cannot cache the information.
   116         //
   125         //
   117         // However if the mtime is far away in the future, this is likely some
   126         // However if the mtime is far away in the future, this is likely some
   118         // mismatch between the current clock and previous file system
   127         // mismatch between the current clock and previous file system
   119         // operation. So mtime more than one days in the future are considered
   128         // operation. So mtime more than one days in the future are considered
   120         // fine.
   129         // fine.
   121         if self.truncated_seconds == boundary.truncated_seconds {
   130         let reliable = if mtime.truncated_seconds == boundary.truncated_seconds
   122             self.nanoseconds != 0
   131         {
       
   132             mtime.second_ambiguous = true;
       
   133             mtime.nanoseconds != 0
   123                 && boundary.nanoseconds != 0
   134                 && boundary.nanoseconds != 0
   124                 && self.nanoseconds < boundary.nanoseconds
   135                 && mtime.nanoseconds < boundary.nanoseconds
   125         } else {
   136         } else {
   126             // `truncated_seconds` is less than 2**31,
   137             // `truncated_seconds` is less than 2**31,
   127             // so this does not overflow `u32`:
   138             // so this does not overflow `u32`:
   128             let one_day_later = boundary.truncated_seconds + 24 * 3600;
   139             let one_day_later = boundary.truncated_seconds + 24 * 3600;
   129             self.truncated_seconds < boundary.truncated_seconds
   140             mtime.truncated_seconds < boundary.truncated_seconds
   130                 || self.truncated_seconds > one_day_later
   141                 || mtime.truncated_seconds > one_day_later
       
   142         };
       
   143         if reliable {
       
   144             Ok(Some(mtime))
       
   145         } else {
       
   146             Ok(None)
   131         }
   147         }
   132     }
   148     }
   133 
   149 
   134     /// The lower 31 bits of the number of seconds since the epoch.
   150     /// The lower 31 bits of the number of seconds since the epoch.
   135     pub fn truncated_seconds(&self) -> u32 {
   151     pub fn truncated_seconds(&self) -> u32 {