Skip to content

Commit 475f536

Browse files
committed
tugger-debian: honor Acquire-By-Hash: yes setting
Modern Debian repositories set an `Acquire-By-Hash: yes` field to trigger clients to fetch URLs containing the content digest of the entity they are fetching. We had support for parsing this field but weren't keying off of it. This commit implements functionality for resolving the `by-hash` path for a release file entry and automatically using it if the release file says to use acquire-by-hash mode. Pre-existing tests should now fetch teh by-hash URLs. The tests pass, indicating this functionality apparently works.
1 parent b343587 commit 475f536

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

tugger-debian/src/repository/http.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,18 @@ impl<'client> HttpReleaseClient<'client> {
280280
is_installer,
281281
)
282282
.ok_or(HttpError::PackagesIndicesEntryNotFound)?;
283-
let path = entry.entry.path;
283+
284+
let path = if self.release.acquire_by_hash().unwrap_or_default() {
285+
entry.entry.by_hash_path()
286+
} else {
287+
entry.entry.path.to_string()
288+
};
284289

285290
// TODO perform digest verification.
286291
// TODO make this stream output.
287292

288293
let mut reader = ControlParagraphAsyncReader::new(futures::io::BufReader::new(
289-
self.get_path_reader(path, entry.compression).await?,
294+
self.get_path_reader(&path, entry.compression).await?,
290295
));
291296

292297
let mut res = BinaryPackageList::default();

tugger-debian/src/repository/release.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ impl<'a> ReleaseFileDigest<'a> {
119119
Self::Sha256(_) => ChecksumType::Sha256.field_name(),
120120
}
121121
}
122+
123+
/// Obtain the tracked digest value.
124+
pub fn digest(&self) -> &'a str {
125+
match self {
126+
Self::Md5(v) => v,
127+
Self::Sha1(v) => v,
128+
Self::Sha256(v) => v,
129+
}
130+
}
122131
}
123132

124133
/// An entry for a file in a parsed `Release` file.
@@ -136,6 +145,26 @@ pub struct ReleaseFileEntry<'a> {
136145
pub size: usize,
137146
}
138147

148+
impl<'a> ReleaseFileEntry<'a> {
149+
/// Obtain the `by-hash` path variant for this entry.
150+
pub fn by_hash_path(&self) -> String {
151+
if let Some((prefix, _)) = self.path.rsplit_once('/') {
152+
format!(
153+
"{}/by-hash/{}/{}",
154+
prefix,
155+
self.digest.field_name(),
156+
self.digest.digest()
157+
)
158+
} else {
159+
format!(
160+
"by-hash/{}/{}",
161+
self.digest.field_name(),
162+
self.digest.digest()
163+
)
164+
}
165+
}
166+
}
167+
139168
/// A type of [ReleaseFileEntry] that describes a `Contents` file.
140169
#[derive(Clone, Debug, PartialEq)]
141170
pub struct ContentsFileEntry<'a> {
@@ -608,6 +637,10 @@ mod test {
608637
size: 738242,
609638
}
610639
);
640+
assert_eq!(
641+
entries[0].by_hash_path(),
642+
"contrib/by-hash/MD5Sum/7fdf4db15250af5368cc52a91e8edbce"
643+
);
611644
assert_eq!(
612645
entries[1],
613646
ReleaseFileEntry {
@@ -616,6 +649,10 @@ mod test {
616649
size: 57319,
617650
}
618651
);
652+
assert_eq!(
653+
entries[1].by_hash_path(),
654+
"contrib/by-hash/MD5Sum/cbd7bc4d3eb517ac2b22f929dfc07b47"
655+
);
619656
assert_eq!(
620657
entries[599],
621658
ReleaseFileEntry {
@@ -624,6 +661,10 @@ mod test {
624661
size: 80488,
625662
}
626663
);
664+
assert_eq!(
665+
entries[599].by_hash_path(),
666+
"non-free/source/by-hash/MD5Sum/e3830f6fc5a946b5a5b46e8277e1d86f"
667+
);
627668

628669
assert!(release.iter_index_files(ChecksumType::Sha1).is_none());
629670

@@ -642,6 +683,7 @@ mod test {
642683
size: 738242,
643684
}
644685
);
686+
assert_eq!(entries[0].by_hash_path(), "contrib/by-hash/SHA256/3957f28db16e3f28c7b34ae84f1c929c567de6970f3f1b95dac9b498dd80fe63");
645687
assert_eq!(
646688
entries[1],
647689
ReleaseFileEntry {
@@ -652,6 +694,7 @@ mod test {
652694
size: 57319,
653695
}
654696
);
697+
assert_eq!(entries[1].by_hash_path(), "contrib/by-hash/SHA256/3e9a121d599b56c08bc8f144e4830807c77c29d7114316d6984ba54695d3db7b");
655698
assert_eq!(
656699
entries[599],
657700
ReleaseFileEntry {
@@ -662,6 +705,7 @@ mod test {
662705
path: "non-free/source/Sources.xz",
663706
}
664707
);
708+
assert_eq!(entries[599].by_hash_path(), "non-free/source/by-hash/SHA256/30f3f996941badb983141e3b29b2ed5941d28cf81f9b5f600bb48f782d386fc7");
665709

666710
let contents = release
667711
.iter_components_indices(ChecksumType::Sha256)

0 commit comments

Comments
 (0)