patchkit-0.1.2/.cargo_vcs_info.json0000644000000001360000000000100126430ustar { "git": { "sha1": "e8253d0f2fbe48dba8c3c2fa32c16ee47918302a" }, "path_in_vcs": "" }patchkit-0.1.2/.gitignore000064400000000000000000000000101046102023000134120ustar 00000000000000/target patchkit-0.1.2/Cargo.toml0000644000000013710000000000100106430ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "patchkit" version = "0.1.2" authors = ["Jelmer Vernooij "] description = "A library for parsing and manipulating patch files" readme = "README.md" license = "Apache-2.0" repository = "https://github.com/breezy-team/patchkit" [dependencies] patchkit-0.1.2/Cargo.toml.orig000064400000000000000000000004211046102023000143170ustar 00000000000000[package] name = "patchkit" version = "0.1.2" edition = "2021" license = "Apache-2.0" description = "A library for parsing and manipulating patch files" repository = "https://github.com/breezy-team/patchkit" authors = ["Jelmer Vernooij "] [dependencies] patchkit-0.1.2/README.md000064400000000000000000000003031046102023000127060ustar 00000000000000Parsing and manipulation of patch files --------------------------------------- This crate provides support for parsing and editing of unified diff files, as well as related files (e.g. quilt). patchkit-0.1.2/disperse.conf000064400000000000000000000000461046102023000141200ustar 00000000000000timeout_days: 5 tag_name: "v$VERSION" patchkit-0.1.2/src/lib.rs000064400000000000000000000000171046102023000133340ustar 00000000000000pub mod quilt; patchkit-0.1.2/src/quilt.rs000064400000000000000000000115451046102023000137340ustar 00000000000000use std::collections::HashMap; use std::io::BufRead; pub const DEFAULT_PATCHES_DIR: &str = "patches"; pub const DEFAULT_SERIES_FILE: &str = "series"; /// Find the common prefix to use for patches /// /// # Arguments /// * `names` - An iterator of patch names /// /// # Returns /// The common prefix, or `None` if there is no common prefix pub fn find_common_patch_suffix<'a>(names: impl Iterator) -> Option<&'a str> { let mut suffix_count = HashMap::new(); for name in names { if name == "series" || name == "00list" { continue; } if name.starts_with("README") { continue; } let suffix = name.find('.').map(|index| &name[index..]).unwrap_or(""); suffix_count .entry(suffix) .and_modify(|count| *count += 1) .or_insert(1); } // Just find the suffix with the highest count and return it suffix_count .into_iter() .max_by_key(|(_, count)| *count) .map(|(suffix, _)| suffix) } #[cfg(test)] mod find_common_patch_suffix_tests { #[test] fn test_find_common_patch_suffix() { let names = vec![ "0001-foo.patch", "0002-bar.patch", "0003-baz.patch", "0004-qux.patch", ]; assert_eq!( super::find_common_patch_suffix(names.into_iter()), Some(".patch") ); } #[test] fn test_find_common_patch_suffix_no_common_suffix() { let names = vec!["0001-foo.patch", "0002-bar.patch", "0003-baz.patch", "0004-qux"]; assert_eq!(super::find_common_patch_suffix(names.into_iter()), Some(".patch")); } #[test] fn test_find_common_patch_suffix_no_patches() { let names = vec!["README", "0001-foo.patch", "0002-bar.patch", "0003-baz.patch"]; assert_eq!(super::find_common_patch_suffix(names.into_iter()), Some(".patch")); } } #[derive(Debug)] pub enum SeriesEntry { Patch { name: String, options: Vec, }, Comment(String), } /// A quilt series file #[derive(Debug)] pub struct Series { pub entries: Vec, } impl Series { pub fn new() -> Self { Self { entries: vec![] } } pub fn read(reader: R) -> std::io::Result { let mut series = Self::new(); let reader = std::io::BufReader::new(reader); for line in reader.lines() { let line = line?; let line = line.trim(); if line.starts_with('#') { series.entries.push(SeriesEntry::Comment(line.to_string())); continue; } let mut parts = line.split_whitespace(); let name = parts.next().ok_or_else(|| { std::io::Error::new( std::io::ErrorKind::InvalidData, "missing patch name in series file", ) })?; let options = parts.map(|s| s.to_string()).collect(); series.entries.push(SeriesEntry::Patch { name: name.to_string(), options }); } Ok(series) } pub fn remove(&mut self, name: &str) { self.entries.retain(|entry| match entry { SeriesEntry::Patch { name: entry_name, .. } => entry_name != name, _ => true, }); } pub fn patches(&self) -> impl Iterator { self.entries.iter().filter_map(|entry| match entry { SeriesEntry::Patch { name, .. } => Some(name.as_str()), _ => None, }) } pub fn append(&mut self, name: &str, options: Option<&[String]>) { self.entries.push(SeriesEntry::Patch { name: name.to_string(), options: options.map(|options| options.to_vec()).unwrap_or_default(), }); } pub fn write(&self, writer: &mut W) -> std::io::Result<()> { for entry in &self.entries { match entry { SeriesEntry::Patch { name, options } => { write!(writer, "{}", name)?; for option in options { write!(writer, " {}", option)?; } writeln!(writer)?; } SeriesEntry::Comment(comment) => { writeln!(writer, "# {}", comment)?; } } } Ok(()) } } impl Default for Series { fn default() -> Self { Self::new() } } /// Read a .pc/.quilt_patches file pub fn read_quilt_patches(mut reader: R) -> std::path::PathBuf { let mut p = String::new(); reader.read_to_string(&mut p).unwrap(); p.into() } /// Read a .pc/.quilt_series file pub fn read_quilt_series(mut reader: R) -> std::path::PathBuf { let mut s = String::new(); reader.read_to_string(&mut s).unwrap(); s.into() }