From f1514dd30194c0060653e07c6f8830a9cb90f0fa Mon Sep 17 00:00:00 2001 From: Annie Cherkaev Date: Mon, 27 Apr 2020 17:03:58 -0700 Subject: [PATCH] Add support for BEP 39. Add update-url field to info struct. See BEP 39 for more details: http://bittorrent.org/beps/bep_0039.html type: added fixes: - https://github.com/casey/intermodal/issues/98 --- CHANGELOG.md | 5 ++- src/info.rs | 7 ++++ src/into_u64.rs | 2 +- src/metainfo.rs | 8 ++++ src/subcommand/torrent/create.rs | 68 ++++++++++++++++++++++++++++++++ src/subcommand/torrent/show.rs | 4 ++ 6 files changed, 91 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4d366e..14df71b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ Changelog ========= -UNRELEASED - 2020-04-25 +UNRELEASED - 2020-04-28 ----------------------- -- :books: [`xxxxxxxxxxxx`](https://github.com/casey/intermodal/commits/master) Improve documentation - _Casey Rodarmor _ +- :sparkles: [`xxxxxxxxxxxx`](https://github.com/casey/intermodal/commits/master) Add support for BEP 39. - Fixes [#98](https://github.com/casey/intermodal/issues/98) - _Annie Cherkaev _ +- :books: [`d077da405e1f`](https://github.com/casey/intermodal/commit/d077da405e1f50e4b1f2dc78cf821105640c9110) Improve documentation - _Casey Rodarmor _ - :wrench: [`f8711a79a3d9`](https://github.com/casey/intermodal/commit/f8711a79a3d92da5b30fd3e8b7bba7a5e2d73766) Improve the done and merge recipes - _Casey Rodarmor _ - :wrench: [`97ee5684f8e0`](https://github.com/casey/intermodal/commit/97ee5684f8e0f8de7dbdb4f930018c8df0f012b1) Don't invalid build cache when `Cargo.lock` changes - _Casey Rodarmor _ - :books: [`c75ec39b14bb`](https://github.com/casey/intermodal/commit/c75ec39b14bb4375a875d2d2c73718b44eb54e12) Remove watch dropdown image from readme - _Casey Rodarmor _ diff --git a/src/info.rs b/src/info.rs index 2954cc5..9038e4e 100644 --- a/src/info.rs +++ b/src/info.rs @@ -20,6 +20,13 @@ pub(crate) struct Info { pub(crate) pieces: PieceList, #[serde(flatten)] pub(crate) mode: Mode, + #[serde( + skip_serializing_if = "Option::is_none", + default, + with = "unwrap_or_skip", + rename = "update-url" + )] + pub(crate) update_url: Option, } impl Info { diff --git a/src/into_u64.rs b/src/into_u64.rs index be7c02c..52c637c 100644 --- a/src/into_u64.rs +++ b/src/into_u64.rs @@ -1,7 +1,7 @@ use crate::common::*; // Systems with pointers larger than 64 bits may eventually exist, but -// for now let's assume that usize is at most 32 bits, and document that +// for now let's assume that usize is at most 64 bits, and document that // assumption with this assert. const_assert!(std::mem::size_of::() <= std::mem::size_of::()); diff --git a/src/metainfo.rs b/src/metainfo.rs index eb15a14..65fb79f 100644 --- a/src/metainfo.rs +++ b/src/metainfo.rs @@ -143,6 +143,7 @@ mod tests { length: Bytes(20), md5sum: None, }, + update_url: None, }, }; @@ -176,6 +177,7 @@ mod tests { md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")), }], }, + update_url: None, }, }; @@ -224,6 +226,7 @@ mod tests { length: Bytes(5), md5sum: Some(Md5Digest::from_hex("000102030405060708090a0b0c0d0e0f")), }, + update_url: None, }, }; @@ -279,6 +282,7 @@ mod tests { length: Bytes(5), md5sum: None, }, + update_url: None, }, }; @@ -321,6 +325,7 @@ mod tests { path: FilePath::from_components(&["a", "b"]), }], }, + update_url: None, }, }; @@ -369,6 +374,7 @@ mod tests { path: FilePath::from_components(&["a", "b"]), }], }, + update_url: None, }, }; @@ -413,6 +419,7 @@ mod tests { length: Bytes(5), md5sum: None, }, + update_url: None, }, }; @@ -453,6 +460,7 @@ mod tests { length: Bytes(5), md5sum: None, }, + update_url: None, }, }; diff --git a/src/subcommand/torrent/create.rs b/src/subcommand/torrent/create.rs index 3088851..bc370a4 100644 --- a/src/subcommand/torrent/create.rs +++ b/src/subcommand/torrent/create.rs @@ -266,6 +266,14 @@ Sort in ascending order by size, break ties in descending path order: --get core.excludesFile`." )] ignore: bool, + #[structopt( + long = "update-url", + value_name = "URL", + help = "Set torrent feed URL to `URL`, stored in the `update-url` key of the info dictionary. \ + Clients that support BEP 39 will use the update URL to download revised versions of \ + the torret's metainfo. Note that BEP 39 is not widely supported." + )] + update_url: Option, } impl Create { @@ -380,6 +388,7 @@ impl Create { mode, pieces, private, + update_url: self.update_url.map(|url| url.to_string()), }; let metainfo = Metainfo { @@ -3123,4 +3132,63 @@ Content Size 9 bytes assert_eq!(env.out(), ""); assert_eq!(env.err(), ""); } + + #[test] + fn test_update_url_invalid_url_fails() { + let mut env = test_env! { + args: [ + "torrent", + "create", + "--update-url", + "not-a-URL", + "--input", + "foo" + ], + tree: { + foo: "", + } + }; + assert_matches!(env.run(), Err(Error::Clap { .. })); + } + + #[test] + fn test_update_url_valid_url_succeeds() { + let mut env = test_env! { + args: [ + "torrent", + "create", + "--update-url", + "https://www.a_real_url.com", + "--input", + "foo" + ], + tree: { + foo: "", + } + }; + env.assert_ok(); + } + + #[test] + fn test_update_url() { + let mut env = test_env! { + args: [ + "torrent", + "create", + "--update-url", + "https://www.a_real_url.com", + "--input", + "foo", + ], + tree: { + foo: "", + } + }; + env.assert_ok(); + let metainfo = env.load_metainfo("foo.torrent"); + assert_eq!( + metainfo.info.update_url.as_deref(), + Some("https://www.a_real_url.com/") + ); + } } diff --git a/src/subcommand/torrent/show.rs b/src/subcommand/torrent/show.rs index b80cb6d..7181914 100644 --- a/src/subcommand/torrent/show.rs +++ b/src/subcommand/torrent/show.rs @@ -133,6 +133,7 @@ mod tests { length: Bytes(20), md5sum: None, }, + update_url: None, }, }; @@ -273,6 +274,7 @@ files\tfoo length: Bytes(20), md5sum: None, }, + update_url: None, }, }; @@ -375,6 +377,7 @@ files\tfoo length: Bytes(20), md5sum: None, }, + update_url: None, }, }; @@ -477,6 +480,7 @@ files\tfoo length: Bytes(20), md5sum: None, }, + update_url: None, }, };