context: copy symlinks as symlinks and improve error messages

This commit is contained in:
2026-07-17 10:12:46 +02:00
parent 2b27b7b06e
commit c4b59a4376
11 changed files with 382 additions and 54 deletions
+72 -9
View File
@@ -119,10 +119,24 @@ fn increment_suffix(version: &str, suffix: &str) -> String {
pub fn parse_changelog_header(
path: &Path,
) -> Result<(String, String, String), Box<dyn std::error::Error>> {
let file = File::open(path)?;
let file = File::open(path).map_err(|e| {
format!(
"Failed to read changelog '{}': {}. \
Make sure you are running this command from the root of a source package \
(a directory containing a 'debian/' subdirectory with a 'changelog' file).",
path.display(),
e
)
})?;
let mut reader = io::BufReader::new(file);
let mut first_line = String::new();
reader.read_line(&mut first_line)?;
reader.read_line(&mut first_line).map_err(|e| {
format!(
"Failed to read first line of changelog '{}': {}",
path.display(),
e
)
})?;
// Format: package (version) series; urgency=urgency
let re = Regex::new(r"^(\S+) \(([^)]+)\) (.*); .*")?;
@@ -132,16 +146,37 @@ pub fn parse_changelog_header(
let series = caps.get(3).map_or("", |m| m.as_str()).to_string();
Ok((package, version, series))
} else {
Err(format!("Invalid changelog header format in {}", path.display()).into())
Err(format!(
"Invalid changelog header format in '{}'. \
The first line must look like: `package (version) series; urgency=...`, \
but got: {:?}",
path.display(),
first_line.trim_end()
)
.into())
}
}
/// Parse a changelog file footer to extract maintainer information
/// Returns (name, email) tuple from the last modification entry
pub fn parse_changelog_footer(path: &Path) -> Result<(String, String), Box<dyn std::error::Error>> {
let mut file = File::open(path)?;
let mut file = File::open(path).map_err(|e| {
format!(
"Failed to read changelog '{}': {}. \
Make sure you are running this command from the root of a source package \
(a directory containing a 'debian/' subdirectory with a 'changelog' file).",
path.display(),
e
)
})?;
let mut content = String::new();
file.read_to_string(&mut content)?;
file.read_to_string(&mut content).map_err(|e| {
format!(
"Failed to read changelog '{}': {}",
path.display(),
e
)
})?;
// Find the last maintainer line (format: -- Name <email> Date)
let re = Regex::new(r"--\s*([^<]+?)\s*<([^>]+)>\s*")?;
@@ -159,7 +194,13 @@ pub fn parse_changelog_footer(path: &Path) -> Result<(String, String), Box<dyn s
.to_string();
Ok((name, email))
} else {
Err(format!("No maintainer information found in {}", path.display()).into())
Err(format!(
"No maintainer information found in '{}'. \
The changelog must contain a line of the form '-- Name <email> Date', \
but none was found.",
path.display()
)
.into())
}
}
@@ -283,9 +324,31 @@ fn get_maintainer_info() -> Result<(String, String), Box<dyn std::error::Error>>
}
// From git config
let config = git2::Config::open_default()?;
let name = config.get_string("user.name")?;
let email = config.get_string("user.email")?;
let config = git2::Config::open_default().map_err(|e| {
format!(
"Could not determine maintainer information. \
Neither $DEBFULLNAME/$DEBEMAIL nor git configuration is available: {}. \
Set the DEBFULLNAME and DEBEMAIL environment variables, \
or configure git with `git config --global user.name` and `git config --global user.email`.",
e
)
})?;
let name = config.get_string("user.name").map_err(|e| {
format!(
"Could not find git 'user.name' configuration: {}. \
Set it with `git config --global user.name \"Your Name\"` \
or define the DEBFULLNAME environment variable.",
e
)
})?;
let email = config.get_string("user.email").map_err(|e| {
format!(
"Could not find git 'user.email' configuration: {}. \
Set it with `git config --global user.email \"you@example.com\"` \
or define the DEBEMAIL environment variable.",
e
)
})?;
Ok((name, email))
}