1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::io::Write;
use std::path::PathBuf;
use manifest::Config;
use listener::Listener;
use md5::Digest;
use md5;
use file;
use std::collections::HashMap;
use error::*;
use pathbytes::*;
use archive::Archive;
use wordsplit::WordSplit;
pub fn generate_archive(options: &Config, time: u64, asset_hashes: HashMap<PathBuf, Digest>, listener: &mut Listener) -> CDResult<Vec<u8>> {
let mut archive = Archive::new(time);
generate_md5sums(&mut archive, options, asset_hashes)?;
generate_control(&mut archive, options, listener)?;
if let Some(ref files) = options.conf_files {
generate_conf_files(&mut archive, files)?;
}
generate_scripts(&mut archive, options)?;
Ok(archive.into_inner()?)
}
fn generate_scripts(archive: &mut Archive, option: &Config) -> CDResult<()> {
if let Some(ref maintainer_scripts) = option.maintainer_scripts {
for name in &["preinst", "postinst", "prerm", "postrm"] {
if let Ok(script) = file::get(maintainer_scripts.join(name)) {
archive.file(name, &script, 0o755)?;
}
}
}
Ok(())
}
fn generate_md5sums(archive: &mut Archive, options: &Config, asset_hashes: HashMap<PathBuf, md5::Digest>) -> CDResult<()> {
let mut md5sums: Vec<u8> = Vec::new();
for asset in &options.assets {
write!(md5sums, "{:x}", asset_hashes[&asset.target_path])?;
md5sums.write_all(b" ")?;
md5sums.write_all(asset.target_path.as_path().as_bytes())?;
md5sums.write_all(&[b'\n'])?;
}
archive.file("./md5sums", &md5sums, 0o644)?;
Ok(())
}
fn generate_control(archive: &mut Archive, options: &Config, listener: &mut Listener) -> CDResult<()> {
let mut control: Vec<u8> = Vec::with_capacity(1024);
writeln!(&mut control, "Package: {}", options.name)?;
writeln!(&mut control, "Version: {}", options.version)?;
writeln!(&mut control, "Architecture: {}", options.architecture)?;
if let Some(ref repo) = options.repository {
if repo.starts_with("http") {
writeln!(&mut control, "Vcs-Browser: {}", repo)?;
}
if let Some(kind) = options.repository_type() {
writeln!(&mut control, "Vcs-{}: {}", kind, repo)?;
}
}
if let Some(homepage) = options.homepage.as_ref().or(options.documentation.as_ref()) {
writeln!(&mut control, "Homepage: {}", homepage)?;
}
if let Some(ref section) = options.section {
writeln!(&mut control, "Section: {}", section)?;
}
writeln!(&mut control, "Priority: {}", options.priority)?;
control.write_all(b"Standards-Version: 3.9.4\n")?;
writeln!(&mut control, "Maintainer: {}", options.maintainer)?;
let installed_size = options.assets
.iter()
.filter_map(|m| m.source.len())
.sum::<u64>() / 1024;
writeln!(&mut control, "Installed-Size: {}", installed_size)?;
writeln!(&mut control, "Depends: {}", options.get_dependencies(listener)?)?;
if let Some(ref conflicts) = options.conflicts {
writeln!(&mut control, "Conflicts: {}", conflicts)?;
}
if let Some(ref breaks) = options.breaks {
writeln!(&mut control, "Breaks: {}", breaks)?;
}
if let Some(ref replaces) = options.replaces {
writeln!(&mut control, "Replaces: {}", replaces)?;
}
if let Some(ref provides) = options.provides {
writeln!(&mut control, "Provides: {}", provides)?;
}
write!(&mut control, "Description:")?;
for line in options.description.split_by_chars(79) {
writeln!(&mut control, " {}", line)?;
}
if let Some(ref desc) = options.extended_description {
for line in desc.split_by_chars(79) {
writeln!(&mut control, " {}", line)?;
}
}
control.push(10);
archive.file("./control", &control, 0o644)?;
Ok(())
}
fn generate_conf_files(archive: &mut Archive, files: &str) -> CDResult<()> {
let mut data = Vec::new();
data.write_all(files.as_bytes())?;
data.push(b'\n');
archive.file("./conffiles", &data, 0o644)?;
Ok(())
}