status.rs
147 lines
| 4.7 KiB
| application/rls-services+xml
|
RustLexer
Raphaël Gomès
|
r43565 | // status.rs | ||
// | ||||
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
// | ||||
// This software may be used and distributed according to the terms of the | ||||
// GNU General Public License version 2 or any later version. | ||||
//! Rust implementation of dirstate.status (dirstate.py). | ||||
//! It is currently missing a lot of functionality compared to the Python one | ||||
//! and will only be triggered in narrow cases. | ||||
Simon Sapin
|
r48126 | use crate::dirstate_tree::on_disk::DirstateV2ParseError; | ||
Simon Sapin
|
r48882 | |||
Raphaël Gomès
|
r44003 | use crate::{ | ||
Simon Sapin
|
r49079 | dirstate::TruncatedTimestamp, | ||
Simon Sapin
|
r48882 | utils::hg_path::{HgPath, HgPathError}, | ||
Raphaël Gomès
|
r45015 | PatternError, | ||
Raphaël Gomès
|
r44003 | }; | ||
Simon Sapin
|
r48882 | |||
use std::{borrow::Cow, fmt}; | ||||
Raphaël Gomès
|
r43565 | |||
Raphaël Gomès
|
r45013 | /// Wrong type of file from a `BadMatch` | ||
/// Note: a lot of those don't exist on all platforms. | ||||
Raphaël Gomès
|
r45023 | #[derive(Debug, Copy, Clone)] | ||
Raphaël Gomès
|
r45013 | pub enum BadType { | ||
CharacterDevice, | ||||
BlockDevice, | ||||
FIFO, | ||||
Socket, | ||||
Directory, | ||||
Unknown, | ||||
} | ||||
Simon Sapin
|
r47173 | impl fmt::Display for BadType { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
f.write_str(match self { | ||||
Raphaël Gomès
|
r45016 | BadType::CharacterDevice => "character device", | ||
BadType::BlockDevice => "block device", | ||||
BadType::FIFO => "fifo", | ||||
BadType::Socket => "socket", | ||||
BadType::Directory => "directory", | ||||
BadType::Unknown => "unknown", | ||||
Simon Sapin
|
r47173 | }) | ||
Raphaël Gomès
|
r45016 | } | ||
} | ||||
Raphaël Gomès
|
r45013 | /// Was explicitly matched but cannot be found/accessed | ||
Raphaël Gomès
|
r45023 | #[derive(Debug, Copy, Clone)] | ||
Raphaël Gomès
|
r45013 | pub enum BadMatch { | ||
OsError(i32), | ||||
BadType(BadType), | ||||
} | ||||
Simon Sapin
|
r47883 | /// `Box<dyn Trait>` is syntactic sugar for `Box<dyn Trait + 'static>`, so add | ||
Raphaël Gomès
|
r45088 | /// an explicit lifetime here to not fight `'static` bounds "out of nowhere". | ||
Simon Sapin
|
r47882 | pub type IgnoreFnType<'a> = | ||
Box<dyn for<'r> Fn(&'r HgPath) -> bool + Sync + 'a>; | ||||
Raphaël Gomès
|
r44367 | |||
Raphaël Gomès
|
r45672 | /// We have a good mix of owned (from directory traversal) and borrowed (from | ||
/// the dirstate/explicit) paths, this comes up a lot. | ||||
Raphaël Gomès
|
r45673 | pub type HgPathCow<'a> = Cow<'a, HgPath>; | ||
Raphaël Gomès
|
r45672 | |||
Raphaël Gomès
|
r45011 | #[derive(Debug, Copy, Clone)] | ||
pub struct StatusOptions { | ||||
/// Remember the most recent modification timeslot for status, to make | ||||
/// sure we won't miss future size-preserving file content modifications | ||||
/// that happen within the same timeslot. | ||||
Simon Sapin
|
r49079 | pub last_normal_time: TruncatedTimestamp, | ||
Raphaël Gomès
|
r45011 | /// Whether we are on a filesystem with UNIX-like exec flags | ||
pub check_exec: bool, | ||||
pub list_clean: bool, | ||||
Raphaël Gomès
|
r45014 | pub list_unknown: bool, | ||
pub list_ignored: bool, | ||||
Raphaël Gomès
|
r45353 | /// Whether to collect traversed dirs for applying a callback later. | ||
/// Used by `hg purge` for example. | ||||
pub collect_traversed_dirs: bool, | ||||
Raphaël Gomès
|
r45014 | } | ||
Simon Sapin
|
r47883 | #[derive(Debug, Default)] | ||
Raphaël Gomès
|
r45012 | pub struct DirstateStatus<'a> { | ||
Simon Sapin
|
r47881 | /// Tracked files whose contents have changed since the parent revision | ||
Raphaël Gomès
|
r45672 | pub modified: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Newly-tracked files that were not present in the parent | ||||
Raphaël Gomès
|
r45672 | pub added: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Previously-tracked files that have been (re)moved with an hg command | ||||
Raphaël Gomès
|
r45672 | pub removed: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// (Still) tracked files that are missing, (re)moved with an non-hg | ||||
/// command | ||||
Raphaël Gomès
|
r45672 | pub deleted: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Tracked files that are up to date with the parent. | ||||
/// Only pupulated if `StatusOptions::list_clean` is true. | ||||
Raphaël Gomès
|
r45672 | pub clean: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Files in the working directory that are ignored with `.hgignore`. | ||||
/// Only pupulated if `StatusOptions::list_ignored` is true. | ||||
Raphaël Gomès
|
r45672 | pub ignored: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Files in the working directory that are neither tracked nor ignored. | ||||
/// Only pupulated if `StatusOptions::list_unknown` is true. | ||||
Raphaël Gomès
|
r45672 | pub unknown: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r47881 | |||
/// Was explicitly matched but cannot be found/accessed | ||||
Raphaël Gomès
|
r45672 | pub bad: Vec<(HgPathCow<'a>, BadMatch)>, | ||
Simon Sapin
|
r47881 | |||
Simon Sapin
|
r47880 | /// Either clean or modified, but we can’t tell from filesystem metadata | ||
/// alone. The file contents need to be read and compared with that in | ||||
/// the parent. | ||||
pub unsure: Vec<HgPathCow<'a>>, | ||||
Simon Sapin
|
r47881 | |||
Raphaël Gomès
|
r45353 | /// Only filled if `collect_traversed_dirs` is `true` | ||
Simon Sapin
|
r48136 | pub traversed: Vec<HgPathCow<'a>>, | ||
Simon Sapin
|
r48139 | |||
/// Whether `status()` made changed to the `DirstateMap` that should be | ||||
/// written back to disk | ||||
pub dirty: bool, | ||||
Raphaël Gomès
|
r43565 | } | ||
Simon Sapin
|
r47164 | #[derive(Debug, derive_more::From)] | ||
Raphaël Gomès
|
r45671 | pub enum StatusError { | ||
Raphaël Gomès
|
r45672 | /// Generic IO error | ||
Raphaël Gomès
|
r45671 | IO(std::io::Error), | ||
Raphaël Gomès
|
r45672 | /// An invalid path that cannot be represented in Mercurial was found | ||
Raphaël Gomès
|
r45671 | Path(HgPathError), | ||
Raphaël Gomès
|
r45672 | /// An invalid "ignore" pattern was found | ||
Raphaël Gomès
|
r45671 | Pattern(PatternError), | ||
Simon Sapin
|
r48126 | /// Corrupted dirstate | ||
DirstateV2ParseError(DirstateV2ParseError), | ||||
Raphaël Gomès
|
r45671 | } | ||
pub type StatusResult<T> = Result<T, StatusError>; | ||||
Simon Sapin
|
r47173 | impl fmt::Display for StatusError { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
Raphaël Gomès
|
r45671 | match self { | ||
Simon Sapin
|
r47173 | StatusError::IO(error) => error.fmt(f), | ||
StatusError::Path(error) => error.fmt(f), | ||||
StatusError::Pattern(error) => error.fmt(f), | ||||
Simon Sapin
|
r48126 | StatusError::DirstateV2ParseError(_) => { | ||
f.write_str("dirstate-v2 parse error") | ||||
} | ||||
Raphaël Gomès
|
r45671 | } | ||
} | ||||
} | ||||