xvc_pipeline/pipeline/deps/
regex_items.rs1use std::io::{self, BufRead};
4
5use regex::Regex;
6use serde::{Deserialize, Serialize};
7use xvc_core::types::diff::Diffable;
8use xvc_core::{Diff, XvcMetadata, XvcPath, XvcPathMetadataMap, XvcRoot};
9use xvc_core::persist;
10
11use crate::XvcDependency;
12
13#[derive(Debug, PartialOrd, Ord, Clone, Eq, PartialEq, Serialize, Deserialize)]
15pub struct RegexItemsDep {
16 pub path: XvcPath,
18 pub regex: String,
21 pub lines: Vec<String>,
23 pub xvc_metadata: Option<XvcMetadata>,
25}
26
27persist!(RegexItemsDep, "regex-dependency");
28
29impl From<RegexItemsDep> for XvcDependency {
30 fn from(val: RegexItemsDep) -> Self {
31 XvcDependency::RegexItems(val)
32 }
33}
34
35impl RegexItemsDep {
36 pub fn new(path: XvcPath, regex: String) -> Self {
38 Self {
39 path,
40 regex,
41 lines: Vec::new(),
42 xvc_metadata: None,
43 }
44 }
45
46 pub fn update_metadata(self, xvc_metadata: Option<XvcMetadata>) -> Self {
48 Self {
49 xvc_metadata,
50 ..self
51 }
52 }
53
54 pub fn update_metadata_from_pmm(self, pmm: &XvcPathMetadataMap) -> Self {
56 let xvc_metadata = pmm.get(&self.path).cloned();
57 self.update_metadata(xvc_metadata)
58 }
59
60 pub fn update_lines(self, xvc_root: &XvcRoot) -> Self {
62 let path = self.path.to_absolute_path(xvc_root);
63 let regex = self.regex();
64 let file = std::fs::File::open(path).unwrap();
65 let line_reader = io::BufReader::new(file).lines();
66 let lines = line_reader
67 .filter_map(|line| {
68 if let Ok(line) = line {
69 if regex.is_match(&line) {
70 Some(line)
71 } else {
72 None
73 }
74 } else {
75 None
76 }
77 })
78 .collect();
79
80 Self { lines, ..self }
81 }
82
83 pub fn regex(&self) -> Regex {
85 Regex::new(&self.regex).unwrap()
86 }
87}
88
89impl Diffable for RegexItemsDep {
90 type Item = Self;
91
92 fn diff_superficial(record: &Self::Item, actual: &Self::Item) -> Diff<Self::Item> {
94 assert!(record.path == actual.path);
95
96 match (record.xvc_metadata, actual.xvc_metadata) {
97 (Some(rec_md), Some(act_md)) => {
98 if rec_md == act_md {
99 Diff::Identical
100 } else {
101 Diff::Different {
102 record: record.clone(),
103 actual: actual.clone(),
104 }
105 }
106 }
107 (None, Some(_)) => Diff::RecordMissing {
108 actual: actual.clone(),
109 },
110 (Some(_), None) => Diff::ActualMissing {
111 record: record.clone(),
112 },
113 (None, None) => unreachable!("Either record or actual should have metadata"),
114 }
115 }
116
117 fn diff_thorough(record: &Self::Item, actual: &Self::Item) -> Diff<Self::Item> {
119 assert!(record.path == actual.path);
120 if record.lines == actual.lines {
121 Diff::Identical
122 } else {
123 Diff::Different {
124 record: record.clone(),
125 actual: actual.clone(),
126 }
127 }
128 }
129}