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