debian_watch/
lib.rs

1#![deny(missing_docs)]
2//! Formatting-preserving parser and editor for Debian watch files
3//!
4//! # Example
5//!
6//! ```rust
7//! let wf = debian_watch::WatchFile::new(None);
8//! assert_eq!(wf.version(), debian_watch::DEFAULT_VERSION);
9//! assert_eq!("", wf.to_string());
10//!
11//! let wf = debian_watch::WatchFile::new(Some(4));
12//! assert_eq!(wf.version(), 4);
13//! assert_eq!("version=4\n", wf.to_string());
14//!
15//! let wf: debian_watch::WatchFile = r#"version=4
16//! opts=foo=blah https://foo.com/bar .*/v?(\d\S+)\.tar\.gz
17//! "#.parse().unwrap();
18//! assert_eq!(wf.version(), 4);
19//! assert_eq!(wf.entries().collect::<Vec<_>>().len(), 1);
20//! let entry = wf.entries().next().unwrap();
21//! assert_eq!(entry.opts(), maplit::hashmap! {
22//!    "foo".to_string() => "blah".to_string(),
23//! });
24//! assert_eq!(&entry.url(), "https://foo.com/bar");
25//! assert_eq!(entry.matching_pattern().as_deref(), Some(".*/v?(\\d\\S+)\\.tar\\.gz"));
26//! ```
27
28mod lex;
29mod parse;
30
31pub mod mangle;
32#[cfg(feature = "pgp")]
33pub mod pgp;
34pub mod release;
35pub mod search;
36
37/// Any watch files without a version are assumed to be
38/// version 1.
39pub const DEFAULT_VERSION: u32 = 1;
40
41/// Default user agent string used for HTTP requests
42pub const DEFAULT_USER_AGENT: &str = concat!("debian-watch-rs/", env!("CARGO_PKG_VERSION"));
43
44mod types;
45
46pub use release::Release;
47pub use types::*;
48
49/// Let's start with defining all kinds of tokens and
50/// composite nodes.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
52#[allow(non_camel_case_types, missing_docs, clippy::upper_case_acronyms)]
53#[repr(u16)]
54pub(crate) enum SyntaxKind {
55    KEY = 0,
56    VALUE,
57    EQUALS,
58    QUOTE,
59    COMMA,
60    CONTINUATION,
61    NEWLINE,
62    WHITESPACE, // whitespaces is explicit
63    COMMENT,    // comments
64    ERROR,      // as well as errors
65
66    // composite nodes
67    ROOT,             // The entire file
68    VERSION,          // "version=x\n"
69    ENTRY,            // "opts=foo=blah https://foo.com/bar .*/v?(\d\S+)\.tar\.gz\n"
70    OPTS_LIST,        // "opts=foo=blah"
71    OPTION,           // "foo=blah"
72    OPTION_SEPARATOR, // "," (comma separator between options)
73    URL,              // "https://foo.com/bar"
74    MATCHING_PATTERN, // ".*/v?(\d\S+)\.tar\.gz"
75    VERSION_POLICY,   // "debian"
76    SCRIPT,           // "uupdate"
77}
78
79/// Convert our `SyntaxKind` into the rowan `SyntaxKind`.
80impl From<SyntaxKind> for rowan::SyntaxKind {
81    fn from(kind: SyntaxKind) -> Self {
82        Self(kind as u16)
83    }
84}
85
86pub use crate::parse::Entry;
87pub use crate::parse::WatchFile;
88
89#[cfg(test)]
90mod tests {
91    #[test]
92    fn test_create_watchfile() {
93        let wf = super::WatchFile::new(None);
94        assert_eq!(wf.version(), super::DEFAULT_VERSION);
95
96        assert_eq!("", wf.to_string());
97
98        let wf = super::WatchFile::new(Some(4));
99        assert_eq!(wf.version(), 4);
100
101        assert_eq!("version=4\n", wf.to_string());
102    }
103
104    #[test]
105    fn test_set_version() {
106        let mut wf = super::WatchFile::new(Some(4));
107        assert_eq!(wf.version(), 4);
108
109        wf.set_version(5);
110        assert_eq!(wf.version(), 5);
111        assert_eq!("version=5\n", wf.to_string());
112
113        // Test setting version on a file without version
114        let mut wf = super::WatchFile::new(None);
115        assert_eq!(wf.version(), super::DEFAULT_VERSION);
116
117        wf.set_version(4);
118        assert_eq!(wf.version(), 4);
119        assert_eq!("version=4\n", wf.to_string());
120    }
121
122    #[test]
123    fn test_set_version_on_parsed() {
124        // Test that parsed WatchFiles can be mutated
125        let mut wf: super::WatchFile = "version=4\n".parse().unwrap();
126        assert_eq!(wf.version(), 4);
127
128        wf.set_version(5);
129        assert_eq!(wf.version(), 5);
130        assert_eq!("version=5\n", wf.to_string());
131
132        // Test setting version on a parsed file without version
133        let mut wf: super::WatchFile = "".parse().unwrap();
134        assert_eq!(wf.version(), super::DEFAULT_VERSION);
135
136        wf.set_version(4);
137        assert_eq!(wf.version(), 4);
138        assert_eq!("version=4\n", wf.to_string());
139    }
140}