rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwoode1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799
{
"request": "trigger",
"version": 1,
"event_type": "patch",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "4999dcd5a014a245734b6057bafb9a48f172eaec",
"author": {
"id": "did:key:z6MktwkohCx8aHZ1QCjVZUiLmX92oPZFxRiFZkbq32Tk5Tkm",
"alias": "2color"
},
"title": "build/Dockerfile: Bump `cargo-zigbuild`",
"state": {
"status": "open",
"conflicts": []
},
"before": "dc4d5c93963ecb12b66ce850afdc6054c0eec8e5",
"after": "e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799",
"commits": [
"e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799",
"29e032302531e7ba9e7de33733e1d6e3eb114003",
"02be3e8e2cdbd049fe88cb6415f4b8ce70fe65e1",
"b887cc99f19533530d794a0381e8eba7f7b55b65",
"7e62c628f7a3d4a800957cef7d475ef70d0e5aff",
"ed86a2b1146cdcf8acff38188122508890deb19e",
"71694a2d8ee989c6f6970b2307612faf2c62f034",
"7a77ba481c65cc3efcbe5c660ef8dc2997ae6ce8",
"0e5a56f25f51d07290613a9363bd8c0c9fc8e0be",
"d8298a1d4cca9f15b45dafdea98dd1a33823a4cf",
"7e1cb406bb935c3de008d2171e8961f57b4336ea",
"3419821106e274c96f56948a05d2f51f28f5a6c7",
"3fc92f83fe089263c470b328414d923227cf0e4a",
"63ed3890414645e6519f2aa5b4458e79519b60b3",
"6fd73f4f7b6c145a3b9f88f5a735d50907a055ce",
"d285eccb23f3986bfa88fc1af033e6dcb0dc3a65",
"90f448241ebf1ad5e492f3ed160dee33f43a8010",
"a6f938026f81c0c5c21bb2b9da2450d6a86cbc27",
"919d5c780c4da0b5b9f18f1549bc59dffd7125af",
"50129a7179afb4480fb19f184bef8e1f689aa94c",
"ba4ca69404349f48d173a73d57326090cab68206",
"218ba30d73adbab0c2c51c6148efa53354260cec",
"0c2e8c15118b83fb1e20f31c9e679d26ca973161",
"5790e319d08751540070c50fbe8b7af075dd51b1",
"8677fd9ef0b0e308df6eaffa67da29e1d010140d",
"c14346d93a6a6cca7097695ad11d996fc689075c",
"4867917f371f282f81528687c859e1295ec8e608",
"fd4e4903d70ef21477653d1b50900aca2bd9a5a0",
"05a192daffb5c6bc01a362689061e33382782730",
"2747c52beb15db057f289a8f96774ee246de5284",
"fba60164f04f6331c65d89e901f3db67d658217a",
"138404df6fc6076067dab7b49399ee92da79a55c",
"de43682f16ce19c48744799ea8425f16eabaaefa",
"7f5de25223c43ee90365fbbca85fc1bdfb41797f",
"3054779bfa51e7641a192fcdd14c2109e056534f",
"9c06c4086af9cf6383e0caac22514c4045569d2a",
"3da781f9e17789a030703db8f61ca2abe21b78a7",
"17ff650ec10b75036da270f9f6d48dd7152ac01c",
"96d74ea9ba9fd7c2db095f822eeea6c987e27cc6",
"675b82f344a4345b2749498315095f5c7c63170f",
"388d98557809fe24878e2c44b4a9b7cb13ba7485",
"26708e81a8c875c79ae3a6d9e10b6ca54d88c64f",
"392542e923bc9520519c905da8567d6267400619",
"d66f7e598b95e5b81caee1ff7fe7beca99be4f8f",
"31f3d08d638c0785300a11aa44373b8ff9f66d08",
"d7edbfb2179bdf9d5e03f3052944da141d142001",
"5ddd5c64ea253b91562eb79a8bfa11d0a8b154c8",
"a62b80877375e6bafa07adf5ea58037913f8ea11",
"d840fe006ff3d6ab69f15cda77daf26109fecb58",
"16de8f1950825672fe48b901dafa0d009f612b04",
"d7d9df27a567a3f39519f3cc6b440ce480b8885e",
"2a9b5e72e9134b661691439a00c16e4ee3d25453",
"71f39fb195068d598d75f7cd606d41a4f8ad4b10",
"52ac5d3b3efc46fb943fe91c6862286b39bc5406",
"9f05038234c579788bdfcf2b017475968e6de982",
"d18293c6adbb84f3afa0404db7c1697f562c992a",
"4e3c27446866548cfbe18b534c639d2da5aa552e",
"4fff390c32728dba136e9ed1d739769452c3ddb0",
"d4acccf6140ee9c474c9f85fdbf235cca9b07ea6",
"6ba619f9a636fecfe5f30b36ebb6b8c06774d5cb",
"4641c342c689dd9c549af6c0235256fe225b53a7",
"1a5dfc2616ecc5d8ecb281a18b7e9d2c07d5e6ad",
"4f7bde023c8d80c5a4e27ec0493c71340985328f",
"a2eb75688797869c6d9387009fc7c0ba6f9c11ed",
"ca1b4fa7bcf5734e31349fcdf31a197e295b4a26",
"c830053e32947b204d954b15d5113ffb5b245b69",
"71a91042d96bb994c4cd4311d85f5cd1a6311b4e",
"ac607c8cad96205f911fb34c91133e6c31d0135c",
"8731d01bcaa29e203be7d307e8fd31468fc69abb",
"36fc031da22c7ccbfc94545747203bc8da9d17c0",
"f8b5bde40a6de76318aca6a6972ac67391943e6c",
"e880810e48d7f7d740aafdd33898d43b143a7022",
"0ef1f0714dc940787cc74a04daee57eec06d5def",
"64a028353b4b5a657370b9c6056454a8c44747e1",
"e9b999e2dd1950daab2b1405dccd9a99d5e8ffae",
"474b7f36933fa56646e8983414074514a3dc8f78",
"a71f3b7295a425a2219578c4493dfcd01868cead",
"e373f80d085642003424c82fdc3cd470cbfd2d27",
"a0551416f9e247817e5a2ad99a59bb69160bc76b",
"69a4da6ffbced52b3ce6f85dbea508c0833a2feb",
"024006297d887299811fe0fb66f2195e06834ae4",
"caf45f1525cdd419a90e74d192557f7c3f9b5a6b",
"c2af4b59822f550ab8f32e81b845546b10211d26",
"2ae6301f86e93fa9cc21ae67a0ebe4ffba3eea4b",
"008b1a25e14ed764b7bf34d9ed4c53d6401f9e69",
"ee8b7919fcef20e1cd639e47d95d08e65ed03581",
"0a2981d78d9a7cc29c07d30dfa568b1dc2a40ee9",
"a87e0bd1c8262444e63e2f2d0f982f526c145bf1",
"8d50b75826fc3cc348233c7131885143c400a438",
"4751432b3c208650adf2d7d4f6b0485c2c04d4c3",
"828bfd02fa664b93ae0346dacea9008fef7adfd6",
"394ade55761ce7bfd9c8ea99cac6b61efd0030b9",
"0f8e1cc597e386829557cb2f60648b8654755360",
"e0dc14de2b1adcadcfeba9470fcf1d9ba2539949",
"3658ece34f12812dfaa27cbf754589ed2bdbf403",
"8efbf06f7811a0ecc2b50e342b80e7899b5714f6",
"9eeecacf28fd66062236e37ebad76294843b3a69",
"f45a96f0e908971d2b0a132a873d2a5bd6875e19",
"df6524e7e21027c4eb128dd2eaab0a6d70a6d76d",
"0fd0104e8771fa7f2bec64216b3668485ff6b324",
"8ceef3c40571809910e4c207f3e55e95f8834490",
"66ab7f35c933278b932657936ce0c52a02962302",
"027de89cdb93f9f08e46ab76ab38c62c4005724a",
"188f3041d6a72cec34c2d0077aff3b2503d3d124",
"41d776be4120df9f84633f1d54c1a1de27624c4e",
"f31fbf40cede4f228dc3aa7506000362b0baa8f0",
"6d846d754dd3a7dee5e1c03bf242da64060887ae",
"cff80006a26293f3ed8067e9a3d000d593ab4552",
"e4775edf41ffd0d46c5e3d34b0471c92c3ffa044",
"564c167de12cf2ceed58b78a52f944dde0593269",
"f897cbbf2f7bc5453921f60a2a130d6e46bc3aa8",
"fa14b68e27de621990711838ddb95b7098e24cb5",
"ef7d8bb75dc0ba8d8d5054ae48408d314053fd76",
"8ad86c68c4ae4e436cd6204bd35fbc7d70767564",
"6e06c05157361d5bcad8fc6ac20ee84f63e98db4",
"07b838adbf266e861719df51752db3ea4997046b",
"2590fc50cfdb390714a7c012343e8cf0acbf40e2",
"bdbe1e407b67dac979731efdfd02a7a62f48b562",
"837ee79d28d2bc31caa3b39bde9ee05fc3c757dc",
"27e2a9428a1d5ebf827b9e85be2c47035a6ebd35",
"a079825afce63d9d4794caacf87334059fc29e8f",
"4e22e929d876cae06f7e5e9e894c6b7da139257a",
"7d5248a89bebc8c5669c30cb4fd3ad8c267db6d6",
"b5e6d82769dc3fba7db12ca328e61f9840010d84",
"cd57affc36cc0f8f5d5d8e1b1fe25c4ac2966e7b",
"fb80d58af750d525fc2bd8081e5612a3c2726d4c",
"2f1aaa45b2657d51ef5683f2acc86e050c268d51",
"a63f91885f91de789e4aa7c5a053b777eed03343",
"b6f07074d9198bdbf60f49af61ac6416397edb46",
"7daeb3135b9a264e71b631b6896339bea7784590",
"654218e6a56251a09de0f8924119645d62030232",
"82dc3fe20c5328b606031ed186b9fea2dad81ddc",
"8e677a9d90f10f916b6424c57b450222ed8f5ac6",
"62f64744ad1e0b5c0198e1ebe1e602f6344dac11",
"f720526fc9fd457461d6d440b2742355b9df0020",
"21700e4962c0541043ceba7ee37a777eeaceafed",
"ebf0f417f74558fe974fd72dc2ead38e600639b2",
"97f279fe41be6cc48b462a59b45b7de062029460",
"e0e231813fc5bd521941fadf6a0e9c54c03fb9f4",
"108686e299edebec253e1d2e50e1d939947e4208",
"da2c523d411e21bb74ef18f3469d2f8c03658528",
"aae8938c013149de94bd36d76cfa20e59fd4def6",
"94a24a7283c3a65a0ae02cd7de22fd02f07d96bd",
"2768fe79d2b77ff6688fa26fe3c330d3e524e859",
"c174efccb95d1887483c596cab9166c40dd52d2b",
"2349eebf5da5052f546e9e419cf8a5081de6bb8b",
"39972b0c46303a9f0781dd673022780d40888753",
"489360d0e5d92495af49b495e5c443f0245b688f",
"ba4a79af9060548f85106a78eb90625c8d27fea2",
"d8c14222a26750b8153235a7c97b42c6738fabfd",
"b145b95ee4205a1d18fbe6fb912f11c3dd864526",
"442df34be72a0d4e01ef7e10b7afcc4aa0ee949b",
"ee17109501428319311d18f9bfc339a2a6dec88b",
"b12c0f0be4ecb9c02492ff8197c04ff74b62ec62",
"d973a548b976f16663d3535ef5187fbbcfaf81d8",
"3459ad57cc490001bb75e45b187d7c16583be6c9",
"665e640fe487ce8e9c1056845046c9a7e52199d2",
"d230ff72ee190b8818328c1b03fe7b09fef32324",
"df1e3e6129a181af2d8ef1982da4d061429abc26",
"4a05e52ba10da742cf195505daab3ed8212f75cc",
"7b910476c367f70bca91ad8e72195ad712380531",
"1070b777da7dc540ad7e4fe64dcd23870179945b",
"018266023a738c51b3a4bf6abef5bb16ee3b1181",
"07f748475beacd41463ee5ebc0d7a93539ab8f55",
"88bf2a9648750365d4565e32deae35b18808a391",
"e991bd7476d9038eca540218846a0782dfd6abbd",
"178bda36d8a85d3b13505d1bc718cd6fd2811300",
"eb2dded0edcd938cba7d93a401d00c9cf630a296",
"06e201c927bb510fa9ab5400e14257cb5d563a8e",
"f0c6abc6eaa8f2410c0771b364f165d5a62c8eeb",
"c7339615a762465ccaca2a3db139f0e55ab4ae6c",
"db4ad27b4fc9f33ec5cc80caea46e95ad0da630a",
"d734d692692320c90d71fe45d2eb678a06e2874f",
"fda165ffcaef2e320b2ea6296061f89616849411",
"55b4b04002509907a786b5248d057ec2967a1844",
"a294e057305a8fcaf6800a02c923b33b482a1ae3",
"e4a16dc40a87aa603eded45052832cc7ce0d7210",
"b397b1a2491eaca6389cc0acf495b1d92bd6a8fa",
"09e6147ef9307c78c8874f00cf43537b6a34994a",
"90aaec1c9eee77a0beebece48f460c1424c1c8bd",
"a3ff596e22b489d19e3ac3a18e096415707edb37",
"a65ac048cbda3473e7b372375d33e3a357965492",
"9ff0e8b01f56f1ea224a20160c8f8f0068f371de",
"9c375116132095e17993b88f80978eb0cd726762",
"81fd141139111a61da3a84ce1b77b46a5a37d496",
"f49cc5def8cbf823ac8dd0587afb4d6edba4356f",
"dd7c13271f875a2608784258c6501079a04651b2",
"898e00ecf1e25be1089d02b4a8c50f7bd08de4bb",
"0bbedb9650f5a076bd528adaf8f64ed07bc297fc",
"804fa3e44c9f5b26d32f235206be805d531f9ea9",
"cf2829447362f6903bc07ebdffc29f0aa3445014",
"c70d4a29eb2f77703ca7655d6d20ba90368b20d5",
"cf108311dc067ff0c62b34a8345b0f6af5b1ccc4",
"d8bf84c1732c210d3460aabc93808842d2d1e428",
"3e1a02fdb1f86bace1b16452c26fdba5c5b1b87f",
"01df41bf01928748a28845e445b4dd83a2afc5a1",
"70c2f89bdf7b299bfa702f4f7ad6fcda57b47f02",
"21608788cbef30a3b3f92e477a8740ec7e3f829f",
"87347bdfa6fdf2d9a16de1c534862ed62d714522",
"05507f21a9705e0f81c0a8ea6f70014327dac36a",
"0a03f1c84ef0867f08744dcd856e30e27a4ed70a",
"067a9d13bf3c4d7127d07ac9a475255712d4d4f2",
"998ff91e2c25f1432de007c90fb447849ada37d2",
"5bd3569e120a6172d9df68e1d1d0eed15e8104b1",
"f9ae4b75788eecb0797c7f93c746708ce515e267",
"704b6cdabbdf7e16476a651287dbf967ee1f92ad",
"ff8660d872b8053c54f3fc7636ca379d840c38e9",
"7ed9d50ab63dd973c58ba072b914740e57651556",
"09b1f1f77cdec025f8f92f7395a38f76a11a0d85",
"9381232604df687d6abcd3f13b7f90402fdf1070",
"1f40b32b6aedaaff2016cb20f9e2a3d9c681c651",
"ac5fc67428af7e0d4d8231fdd8ec350db56a2586",
"10004025367e26a51125613691177d38335fc6c0",
"9158df5067429282cbec60292316c13b3d965c5a",
"767b80e7fef5be28ce0b2436b6206e2212ebfbb9",
"c5043617b91aae72600a1b27f8ab902b3ecf80d1",
"caee776c388ffac2ea55cc9d1e3d7fa108ca6df5",
"f22811e0159b1ff25df40221a4d2595927543f89",
"277f2615c944828a95ba31c1aaa8be14996b9555",
"9dda890fb54c00507629b1bd46a9e472b9604ccc",
"ac6759b74b220d3d9ac70cc0a665715405eca338",
"d6488920096b8a8601ff3bc82ca089f90e27b672",
"f41bea1d69e451eb597b0aefc1a23314aaad679b",
"ae4a70e3b6ae33ba4714508b896de2f995600a81",
"d197ab613952427c917110af6930a57366d99cdc",
"8622a466c56312199e2b58070a4c7fb3a23697b2",
"620a1ec69792805b7263c13b438585e3cedeb646",
"be5a1742fbc9be2d033b5b6fbc5fb28e081bb6f6",
"0d7bc8d1db6cfa3fc6ad3f633463e99f5da75947",
"420af3b710bfd0663e9ad6220cb10910580bde2f",
"9ea040ccd05e2c7f8b964d99cc1f65233f43271c",
"0a0e70b1d12367a2e85ae720c14cfb0f677a54b6",
"6b460c44298afad6599b223e48bdaa3c7f3ad5cc",
"9177146794c189d3783d93d383356802e759269b",
"ee9a9de36d437286bead79481ec5902a6657afba",
"53db9941460438579219d3e74ea39dcb49294d6b",
"ad068309c9e73c1ee662cbd28f273f019c865206",
"ab3621d5d4266895ba5b0084e0f2a58a64453a6b",
"f5c39dd6037ccbc05a95fe9f211ac76fb04ab3ed",
"baf533b37b99f0c2d6111827144af94a19d84ff4",
"342b4d963a430342613083eaf86e9efa8469f016",
"622f3827b5848b6d5922c881b8e488894a2a5c73",
"2707f6b4b106e40ee1d2fe84926f85d12d43e313",
"3486c028ea92490a4fec51245ad99372a31bc7f8",
"5991bdfa9a209fa8193d919de3565c346cd934f3",
"2871417808925683d7831ebd1706e9fc12861639",
"4ca2098cb787bd4b6309e7113bec3351a5b6c1ab",
"64a419d79cd76a3e65ed4e9265ec42f4c72ee15a",
"3f81e83d3624dda5ab162cc1ce1a107a7b9960bf",
"080790d84eb64504406e8f4d309e9049bdfa89ad",
"80d30d3b594264277fb827f0536788ea91eba13a",
"ed340f57242c0d9c80c2319056705f997f01507e",
"e87af868dba6293c52eabd01a0b34cdafb4d34db",
"8724ebe7800c557b63b2ed9ca3691e7bd0ccbae0",
"fb40bdc0ac152dedbfec27f33d6e417462be7e75",
"455138f4a7114437b5ca686991227f3531cad915",
"998f527bd4d971525137458adbb6e44efa4ad52c",
"a45a1078abeb1cfda2bf659680c81801a651c569",
"5dae2a8b58d81d7ffd1966e0048a76834962376b",
"a1017050121d92a8643d05b596f6f264ef50fac6",
"08dd1dfda7b867f6843f79ff26c191f21361d84d",
"8391599f611f494bdfed1b52e092df5ae253dff2",
"b482845e712d54fdee00b0548c828e6694a3f359",
"92347a307f2868848a12cbbeea5ce816d77e4dcc",
"b4707e5502a2dbe5c8966c9180ab35c6cac305a8",
"378365aa4200f97fec88b74c0b6edf5bc74f08ce",
"cc70d7dad40d91175eecf3d3a5e4225775d0110b",
"553a3ebd0a205eb08c6ee9c1a415e0dd00f71b16",
"56625a42f75d806fd1f9d037b740d43b5f8025ce",
"2262b8d9bd7880b536c3d1ce8b462e5dc3480303",
"e7d519cf65c4b5c9e5f424a4956882191b2aec27",
"1a31a9f54143a7e35b3840b6a41adb9aab5d5af9",
"e1f16bee26696128ea1c8bb38088a5217c80c92a",
"8f4b90db7b8236d736292144dffb17e8cb4a7b3a",
"7b07e57b9c3cf86e347bd288cc6a8221cb12ff18",
"88a7252e33c32ce33858b29202eb799a923de17d",
"deabe6d2ceac7547343f7bbad7ceea86e19c11c0",
"60f42bff5380e3d9e0c65749e5edb44307a5f74d",
"8dba3ca9de63383531caef6a8ce230ec799ef334",
"3d1b37fcbb485a58e2f3a8ec98337362fdc8c543",
"f46624b81c53f6501df3a8b7ddb80cb8bdd5430e",
"4c605c0671376c6d2c552ea068e7a5db368d3fe1",
"ecca50a5f90279880c8d80987bacba66a0569ec9",
"f65175397f12b1c5626862e450a324b6361b4a31",
"aa177b040037f399312c5f21841f28910a07ce2f",
"cb57e6560fe7767e79b87473a11261fbb82ce84c",
"06ff36ebc443f63b8b735003e0a355f50e53c5bc",
"22287fd94a375b3363d3857e712b4920ed956218",
"3bc8abdc2988eeabe1b03568b5acafb5dec38889",
"099722dd0893559891a80a9d84334bf7573db1e8",
"5d8988b1a242cb1ef006313cb0aa3756e629a422",
"8af0b623fe92ae9de022c8ade70e168d8b42310c",
"bdd991a5f1778628189cf0cafd5d7b18379fdb11",
"802e4726e3daa1353b79dcd1d697e2634f2c673c",
"bfb54bf4be7f52ca016c91620ad8db8e5ec4cda9",
"bbb12796042ec5b590331186eee5230f8c21f4e3",
"f83eb57719b41a5e4b20106af0d5bd397f9ffaff",
"224c03daf1d040da83084928e9a1fe978a5a06ae",
"4a81673d0efe82fce0a7193b6b3e13b735e3462d",
"354805aeb3f871358426753198275738ff76a47e",
"6ce2d00be237e75524cd31129be6766935736c1a",
"2d20e249fdb54e26c514560bcfe611ccd21ec6aa",
"f8ec40a33f58b2111eb6fbb0a75efefff550d365",
"4f647b2a108757ae558de5375a82254b3d33ffea",
"bb97414a2d353270791d3dec924129d97980a1a5",
"f2e96c96cec6315d95608d3a1e93b1a215eb6abd",
"07c624499cdc34a7804f673ed373c66ce2af1acc",
"f00a1624df2d953c01bab2e264ce1b5ec07e50d2",
"8a38fa8c73e0c068a6da54a35bf2cea83cad4bcd",
"fe353ea7e913996704894bb2a2ed4a4117a3246a",
"179a080867d6343f140ec64809ef0143e977d5b6",
"f6bf13422d3fbff6f83e32ad892f2fe559a754e2",
"083c9d1abc68c9937b12aff87637f546b4d8602c",
"421a43376d38b514852c6211d337c89d440c089a",
"6744384acf4cabfbbca9fa2060918c6915bcdd81",
"df31702b8bde763b98a771bf884492d1975ee5a9",
"fc12414778d845505e252416024e1170a2828dea",
"112c901de830f4a3c29631973200ca4ada2fac28",
"69ccabacdd76c1c6e132707ab887a96a61781965",
"1f4de60bac46b031add1596073b3bc0bd77141a9",
"11e80d309412b06d460280cac5a1619dae6bfafb",
"a74befd2a78a79bde492c7bd565176cfc6d18757",
"983e5e19d907b171aa520f7532677a3387645517",
"3e9df1c8e4a3e66a80e21633707a1af2f71d75b0",
"ffe5b9ed08da4c53567fe92d199fe3aec9b0ff1c",
"b0af317eaab2d3eedf2a7918abe8d96bda89e335",
"6e2b710358476291cd60c51478699269b5f34301",
"1df1acabfae9182174e918fa8191fda5f32c053b",
"4e0f739c29dae4e262ebca5865d1980c12ac6d0e",
"09cd3eeb82a1a70d7e7d3ad76ad292c7ace13c44",
"eb8467cb6fc7cdf535872b534014c1424c2402f7",
"bdb2a1fc7f0f8a40a404ad48b3e6a588ac9f69aa",
"576bc6d6af1ff7a52ec8a3b7c14344684e04f0ce",
"3082f9976df65483e282a30c10a97e6f79cd0fae",
"9310b1eff24e9449aa1257592aab4601c7ebc4f0",
"9210f0871a234d2810613943bb9c2258957d79a0",
"430868ffb1067475d730e7549b3f99f21615d9e7",
"9c6bcd27785c94dd7cb8634767ecc1105e35b8c5",
"ac3eba09a111c09c3a6e4ce106520a3aaa1808b2",
"9b9b5ca996528d0b3b7a567fa109534a1b2252f8",
"91b2fd89864dcf7e7d1dbaae61f6b89b1af4fd3d",
"4d57ba496dea6c099990952fd24da3c1b77b7294",
"c23a257f3ca426518c1849ef992b88010a025391",
"dbec748c47ccfa0ecf5a109b53af6e6b0101821f",
"63f96074231205fe0a87567333297acaf59d2c4d",
"f87d2543954b83c8f883eb6d9a4975ffa95ffc7b",
"33a8c09f780bab2a3ecf998ebca40f5bfb8a29e8",
"ca732015fb59855751841f7e3ddfcea9836231a5",
"44244dc00f9a6400c5d81b61ec5c593d69fbe0f2",
"ffc81154e4ede0e93731d108459df77f0b01d78d",
"ae55d935bc607e662480894f9b1c40cf03348f7c",
"547a753768b73f0a375f9648ba3e057a4f650e3a",
"94f65a71db7011c1dd19dd2e2776e57b3cbc8a87",
"adfd89f6093e03a754762038c154ac10d5280b60",
"80c1bba76f432e70d6e766fe750bea70554cfe86",
"a2de55cbb99ae178f09af61e3acf21192ee62097",
"51673679186daa5cd9419f88fb2379b50118092d",
"aa28567035c4b177096749bd875c917e31985e93",
"ef101d9ab9560f905cd784d8303299e2da832b65",
"e822623dc1018390697d0a2d8c41ac03362d5c68",
"bfb2858054c3168c7eac6ed156502811c235cf4b",
"0eba6caf9f09cc0186ecf9ba0520664766a3b7d4",
"22b2871f64ecf34a22d32add0dd59a0c7c96ad10",
"48551cde934370c0cf8a4127385d4a4a41c5ba4d",
"0080813c918c474ec9efe6d69e5def4134729b50",
"5b6ae0ac4a35e829996c1a747798945dfae66167",
"546001253af4d98f8469d3de99c5b3c36fbae8bd",
"96f573b7670d2bbb18bd67037161d54e414fa8fa",
"91590a3287a3aa7294e7766f28759ba8c5350fc5",
"b8f8cfb319643a1ffe14bed5406c4378bdcb49ed",
"b54fc820e92dd9a264267bcc07a36d5503e29887",
"f223afd9d7eb4d1301c7f6fe98bc06418c35c3f5",
"10a82958ca9e6702da0197674b73c1b3dbfe51f2",
"fb1808395e80920c66c53f8c1f39c23c3d6751ae",
"1e132685bc17f9b0a796ca58d7c64b4c0f81c4bc",
"8bac24d6ab961dec6308fdf64b31c41201e9e8d1",
"0494227e7558e4a2bccf768f4f0986e9db55c2df",
"edde15d9ea700a70de04558fafc0b55360e9f5d2",
"263d04b5eae49027b79270cbe0bb887e9b67aa7d",
"597b514d6c4256abcf389cc6e2e642307aa6877d",
"d685d6f91dcffe6e2ffd3447f42934a5be6aca1d",
"78908682dfeca4a184c4b22dba1f616e47ce36c3",
"6e40a617de7df6ba61e81b0092e58fa551fe0ad6",
"5a2e7841c706c319bdf849f4b43bd701a0e86fc4",
"9f91817d25d8d18b1f95b446cfb3e3a8c84bb492",
"46f4c0f38ffb181f6e5787997c6153f18ab22902",
"e7467fb15ff6d679d710c0ee9b6f6d2b94d4c69d",
"6d771abfcc944683f2dbd9e8e4387f3c332bf238",
"ec36d1c3aee2ae6fa2fab240392320e0323427c1",
"07011233eb9cb4427f689e285a7eabe1eddd690d",
"d25fb7f672595267e6c6b8aa80fb10a3c4f546c3",
"5d583338c8def060128ce971c350bf8abe6dd9de",
"86cacfb846af3fde033f2f447c7790a29ccd7190",
"33db6637b437cd4d55b614a6a5b8292c0678a583",
"ef4ddf06c3d1fb5dd878f6ccdc5a8d3eebecbc37",
"07f3d56559d67a390c0598d2944540d6c4e595a3",
"81ca4b9eda4a618ee3c68ec1ac59b74e22f7cc44",
"e245e3115bcb644ebf8ae99338c6061b397dddd5",
"47063057a83d1647dba44bad093165662c050833",
"8b166b232760ed4cae4f2009a6f96d79858db9c3",
"7fb032da9b3b39d5d7f3576ecfcfdde6628e240e",
"404fe33a8871e53092ed96be41fc92bf08d68f60",
"7f19044a727f7776e9d66947e727602cb9e6d2b9",
"8bc3ffc0b0ffba55235b1c2ef79e02f806297cd6",
"372a78754a025d493906c9357d7a906b1f92dba5",
"9a4539fe82f5a0d3afa3659116fbd1cf074ca866",
"b5dc3486db0805641f8c90a4df5ed012bef7f26f",
"14493cbfbf0d620fb67d40bec1a06f2fbffd7744",
"9fda8c6d8f8a00102a7983d9dfa9bc624c91daab",
"d9915d275fd07d20db08cf7d3488f8650e66b88a",
"c627e68fdbc728d5318f3c94c9a3d97d27cab03c",
"a6a3716f5d11c3fc7f255ad7f18d3cd7a8c4a50b",
"fa1699e5d02ccb54f628638e64d7b2eb43a780b8",
"d01ff2e79d7159fd96b5b580b59224562d66d840",
"c237a3fe479050691001ad7487c6ec151dbb797b",
"9fd4f00c2301c0f6db684f6076c49592ae93277d",
"d7e7db35edafa54d54730a5d74812f4c24373d0d",
"026dcdb24a0b295eddafd1915fdfc12162d49cd2",
"a9c1c6ef54af56fa371249af1ce5d962659af591",
"8660b2f00417d91fc227e06a0fd95f53ad32525c",
"4a731e34e1d705699e09ca58deff443ba9a822a4",
"dafd3527ee1059e33508850c9c7595eb37690ced",
"c9450fe84a778a7a79931125f98e7e4fc9a209b4",
"244be71596106ea14e8201e89032d8208fb11f56",
"674586519732d8ded63d00a2c377bf4a41a78d8e",
"a2e72b48e79d090d33f6c13c485239947de0522e",
"addce859f5b8acce5bff223e4fe3b0112bd54013",
"c824d317e47588687bbcc2ad76d84280a42582ea",
"748ddade2feb6f00245c2ba878bd54842dc57506",
"35d71f59096d3485ca18559bf64b55eb5fbce998",
"363a7231e5206e8ef0a7e947a02c852f10a86d8b",
"725ced09d54b4a86a863f0772dcef8749d5f476f",
"6967bf8fcac4a28c6690e6e98e084178dd33e05f",
"20598d39a03c8f9d7ee10e4c55459afb9ed37374",
"0f9eace839ecadc7d2e6501e14e51ecc32bcbd98",
"304a66311aeb80122f711362c952c0dc34962c27",
"393eca39767aa2478475b593ae39b8b4b8f731e6",
"d40fa9a34745b4560f0eae1e9e234282c4b16d05",
"d3bc868e84c334f113806df1737f52cc57c5453d",
"52a660fd3bd0d030614f636523fce78039260e8a",
"99d92421225767a3c17eb0bd0f040cae01e87673",
"52e5581228f55f344e07ea900313062581fa2324",
"281f92e9ff35d5956a19caa54b629af3a226fc68",
"eea3617781d50dc9f908e98f10c39a9ed125d08f",
"a1fd9e04fee05083535f8ec83a05f6a56497152d",
"0736977170c53c41aecf6321ae66560534c9409a",
"9e8f09a1447f9c10536e5b278645688f68de8702",
"0c47d06f2d63a7bbd9c4c401b8b4794a1528284f",
"f4495e92bcfb921b93872e253623ad4373431d0b",
"74fa4425a130c38d06602f46d530c8c079350682",
"06fae85e6709056a85ea143461e457e7aa0fd233",
"f2ad54542e179e7560fc4be4842fd29b8e8e93bc",
"768ecf56ba0ad9dd1a0c1412b57db80275fc9466",
"01c60388db1d109198fbe3922a7b4020f94b25ed",
"58624148d465d0547581a27a93b9a9ada4fe9edf",
"60871de89dda1b18fadb2ce5a2177c6c22e0ffac",
"0e45347b92ba6c78eff9dd66ea11e15c220a6148",
"ba9c09facb99dbfb726e9cc3e261902f889beeb6",
"39a58ded05d378aa944a4cb44368d1ea0baf7280",
"f7ff4d8f4e9524b48da8c9c5ca21b8cda4a07327",
"b8502397a5656a85d1c9c99790f5b199085883df",
"ba8d6b88642c2c1155c12e4afa177b3cadb9aa08",
"e78d477bcf78be33188947da912935976ba28fb9",
"759a6fb98221d222ce515619a5526292a78d3995",
"7bac17146c40b32b2ce0e27b96a555a44f3ef2ba",
"cb3ca6225f4ae3531286b559e15135e7b78e8b62",
"9dbbb01dc6b0f335b45dac58a24d137d6167ed35",
"57da779949abe444ecb8c5ab154e43b8ab9da2da",
"ff85c74eaa2f4d01382fe90ab0525ec78f72b04c",
"1b986af0060a10412df0c70705377c17622f5756",
"fa82bd5f7667f8f6c2701bf245ad7276d0483ecb",
"45e6afd0101f109637a071d0c1bd0c6e97cb9e48",
"d282e0d0f82e2cd7ca2b50925b3a87d48fe64c5c",
"7d2842a458dd60d12b34831cf4d633949df78f7d",
"c1ab7c386eceda0accc37374ab0c706420c52206",
"18d7f99e333d6df7791921ea51588ff62a5c3dd3",
"4ffabde605f135d8c736c5d1d07f8a996dc59728",
"b2568f0b47da8382348e3acbf3e04d8e5b1a999e",
"4753b889dc0280ca4b3e7e1896f12f649bc1e663",
"8bf655ef9789d5aec25acb623d4653ba6349d184",
"a1c1b03b6692f5ccfa617d5f4acff1731ac045ef",
"cd4532ecd514198cb48448ee6c21afe1e6fb1e66",
"dac099e4f1777191985b9ed8172148c78e0df137",
"d39e485c13c34203896936b1beda98fa726d0a74",
"1f3dc6aea0f020c6103c11676a0a7b3fa51386cd",
"7a1e6a242360ae9edb408ca57c275933e9aaa6b9",
"5aaf978f972054dd81777d26b47f967eb9d6f00f",
"f3afe7b02ae55f8a9cd28c50335453b5b2b4d59f",
"f4aee203abb15130745c5195bbc32fd373286991",
"6cc3da95e6bee6bae062da2af8ebdffd71aa183b",
"d36bf41f254f1097077dedc8a0c164ad61f93810",
"9ff67562cbbc8abba3fc3b97831c575db289b8e7",
"df8e4e6c88a8bfb6c1ec6b07dcda64093b477cbe",
"7c9236084237718cb3a3b04be81a4151438b3e0c",
"6291cae59296a04e7cd9d52cdeadc065e44a6fc9",
"f018b434cbc42ec45851a943d91f4b9e67f82eb8",
"9ea1ea243377e73a9c73008387c650cba09dd3d0",
"e9245b630d728672d2b3d6ff9265fa4f1a86f13a",
"b04f487b3ae2efcd23f52f8138abe32e73a718fd",
"9a98cf7b1623e933015313b911738982fc27e66c",
"bab3f82abdf0b75f0a3addd26fdab1c42526ff96",
"a0b434c3201d398732bff3c3c7e92978a7427416",
"9dba9130f8771108e2179dce84b182838be37c24",
"f9a36ef7ac914f9e84de607ef501a21f9068e5e6",
"18d6ce94776b410ab5377ac49f5e545ba363bf21",
"c0ae5e32d9eabfb6836050240fa0b27a732bf5cf",
"963b4ded2befca835e930a72c3082b209d996984",
"84e9ffe4dc5ca037ff6eec2456382c268b44fe2e",
"186d8d30fe2365d0f3f68f3bdf17f045bad7a107",
"3a11074600bf87c51a81145ce420d9a247ab521d",
"156664676286a18b8e775eac0c960129702d97c6",
"d596b14e4846e6ace3c1d275546068af68244ce5",
"4c759a26740aa55d8c4d2b5475b44e85451b7145",
"57a44daeb270c423d1b9e467ae2a103d914db97d",
"89478b16fec06008f7e31ecc8d372b9466cfa801",
"423cf604e1178d62c6952f866b4b5d0b9667aca8",
"30701cc6fbfea03f7ac0e4b7f5af883592791abf",
"057edf55b857783b27bef58b7177b0ffc41a6af6",
"ae06111e07560ca36357dc2d1cd3d4d8cdd81b71",
"4d7b942b7555b2c334a45b05cd0ee074cf9fa0e1",
"6d2a99e1aef4830877e1b1e1c72a3919c3fdb0dd",
"a69420b9b73c0c3916ddb5b47857cdbcc03ab7f2",
"d36ed7c8af6ddfdfbc7d47260dc0e00c30ca7fbd",
"27493c2229766fc14268dc619fbec0e83e4f835d",
"56253b529ecbcb1ae5c7d67605d2b8e4382eaf29",
"bd30e80b9a3e6737b830e813f270de61e8eec5ea",
"119445ce6c9be26a3fae1b0e06f34292c5806cd5",
"56ece480ee723273439874d2260b5b1c9ab78749",
"3cd1af1dd55a76653cc166a6581af7ea684573f6",
"5aca9bf16aff8323009b11137c4e998315128d1e",
"d88ef3fa661679300aed2c9aa003955a0b6478ec",
"a4806f2718a7c0fcbf73631e19b7ed9dd8eb8f52",
"1fa14ef529f20e08c29af12d0b11f26a7ca3a5fe",
"94e0a5128d7f34fb5e8e3ce74f21cd9bf05a39f7",
"4286590fd981f74e635556a942b59d7dcb6d1067",
"0e9d7607e4aa0b9673af42cd2de6f6769c87d627",
"5fa68ed81499f6b887bcda74fb1bb5c80926f7f2",
"c96aea0699a79dfe6e2111ae4d0961454b27e036",
"832598ceb7bfc189ffb387bbbd640df689ca78b8",
"cee3659ed519c7601f18859f3ffbcfc0ddb5dc5e",
"306d0afbfe48f668b1c6c11b64b0d487bdb3dd44",
"0684d1ccdfa2f89a570f5599a411fbfa82b1830a",
"dd13eed1d03729cb3224df6400cd7b8c3cf653d1",
"b5e8776efdf1db2c469ecacc61cf5eaeae3b802a",
"84320919e2cfb2abda9e7c97dbbd2234f8f7f5c6",
"7862e108b656dfdac3f44fe6c27ebefd1e679d80",
"391571178e26bcba2e3e360b4c0db6c4b6f8178c",
"8070f98a5b8a12c532314b789607326c7eb1984f",
"980ed5618602567dd13b0b522180e0fe889f701c",
"0d628a45e27776d97574287ee69594408f59faf8",
"b1eedd3b64e497a645fd1bcdbeec9159a185e505",
"61a9b2140f1f777ec7504ae58fbd4246deccbb5f",
"2c1972151ddad7bd018a913a86bad217a6b753e8",
"38713a8e628740007a811c70cdc26aa31897339b",
"912a5ca42b2c8a0b033d783954e2eba49018d96c",
"fa94638abb8037f6a3c7ade8ac8a1cdf3a52cad4",
"7425ae4b49343c287616daaeeb2ac69eb5bad949",
"5099c25df7b06f0cb800d1e1c3a354334a955d19",
"a1fa38018e0160484cfe1152b13a653e503d43b5",
"d530f1265e52ab90a4e4d423502379ab9aa5e5af",
"730d696d74bf79099b5577d1e6e9d9020e5c7f91",
"dfe3b501c76f78d1d7f04c663f3995ba914b5aea",
"ed2b36cf9c930724a752458752d71825634f73a4",
"9055a2043ccb6741d703e4f9b1dcf7d9e5cf07e5",
"e831aeb57b09aae1eaedf2fec62830d8e59078fe",
"8fbdd46ce424520502feb3fde6e7ee035b3b2f8d",
"4894657bcbd1c45a797391fc3580699bcddf8a9d",
"25d1974c60a4a152383761cc7c484b3be173ab5e",
"44f52f4c18290059931d2d7bec37c0eba42ee75f",
"dd122f10cfc4ee2dca8999503e25b53eefae907d",
"5974fa32d022f6bfcf18d9dacdd3c2c9113b1a45",
"c06b00e330d82c8b8221cc8f8776c883208d159f",
"31607cf7ad443475c66eabb846b1bdd37e5deff1",
"2d0db3c6b244fd9978173ac2cac05a7e21f6c15f",
"03bbe52417f131ec721a7c1cc57185019f0298a3",
"865abd35e225116f4bec440ba9dfd266d67a9bce",
"9081c11b98cd9b8fd6c2633b632ecc8bc8e54423",
"53a1286901e6e895001314c5339363800c29f6df",
"94d7799ffec18cb8e7884050fc0e3effc19b59d9",
"56ee626a51a4ffe14bbbdb6763f29e8e5d58449c",
"41f77a495b953bbf9b7dbad63ab8e6750505f846",
"613c4e83e0405f100d7a6f2ece44465ac0013997",
"993428df5657e18b167ac0e6206efa0b6908d8c0",
"aeba81f4d9cf35b5bfcb0af19f5055411e4b679c",
"35a01898e6fbe598b57d4beaf452b58a676062c9",
"8ee32168b373d5e82689bdef4dc98f70f75daa3c",
"ebf7d876b4d7fc41775febfe49cb0a702f266e53",
"90cf37c471ce531b90aabb048ceaca25996da2cf",
"990edbf055c77390ae2f153c8c1f0afbec2977ac",
"50fb228ae4c0c8f68413dc7922a1e2a32ace5655",
"450b664ad80c42ac452407008aeca2a8140c4f1e",
"8fb2d96b5cdbe629b2e25bb968c76c381b9f2be2",
"930ec175f14b77fd700f06fdc02b8719282ea5a2",
"537eaba8d16cbc34dab2a04e212a704b3bb68f7c",
"d7a4137e23b68b768f0d41349e5d0664bea772d0",
"27ee6e10380ec017bce23d7496de4de8a880c8b7",
"fefa28372d0bbc758ab6a8440d29ba2233b71c94",
"ffbbb374c1f28a2597922e936e174810ce39023a",
"faeee9f3701869fa927f3dd8b9c3406690e46556",
"82ad52b169ff5ce2f81440f79e2325afae39c1ab",
"fe09cd4a007bb9449b772bb5639ade6c4d3ddaab",
"204db22bbe282611385d0add2f80705479983ad8",
"1cab036c331f5ac071f002504c44b01e95b8f25a",
"9e20890965cb5ed96d2175fed8244d1358e29985",
"f0e3ca34039879850cda5e7b5f66cc9d155406c0",
"7cf73300f6559b3581455e63d8143647445af960",
"eccfd6baf3a57448c3ed81569e71a01629efa280",
"c33c26fa78bc80d8bdaf2919f5aed9f36afac0f1",
"15adb161357262f9287d1b90fffda55f6c2611c0",
"91eb6fc078727337449c203b8cf54aba4f40d816",
"36d5a4c8b057830ed9556d6330e271e75d015091",
"73f9a350331f6c6269f7f60e1e94612c948fb423",
"589925e3a3d792b321661a2e3f33b1f38be15063",
"8b1d475170accf4288cfe39286b9c959618cf736",
"d2ab7b1b46935c95a46d0e7ddac3130b595eb15a",
"1c9a1b4fcb52854003a9c7641cb7028a52facaef",
"e63c30976e69d68a9542d7b348ac15a688aa527f",
"b937a93892db3d80833b3cdde3bc37935151e274",
"60959f7e83e80b3a98d06cddee9ebd4b2cd39183",
"67a4a712e441007f8edec6f60a9fe5300581d85a",
"bd5436d7912d7252d20fbb3c403f61261a0506eb",
"b41ce2e6fa58f7c0bcfa60204e4fc7ea44838d71",
"f6d3dae4c7918553c9bb64fd03b19b9da2767d0a",
"a4e66d141e02a3b1e58b21b4c67cab61a971da5a",
"67dee65549b9bbd8fbd3bfec47c5f9b78c177d26",
"6d1abd283349676835c2f4975ab05d15637eae62",
"b020543c4b5ba30567a710337a2602c75711310e",
"ee1f55420aab36b786848854bb9bf3b1d2070e6a",
"eeadffa636b2fe9b0319afff493d5273426ad8a5",
"958422a7c4898e1edb9a514e84eaa2d5664ef36f",
"95b3d10961dd5db11396d548df11e91507632ffc",
"9236277abf85f51322d59f4a9e13a228edcf7157",
"e3cb36d95008543d3a5bf95259c0d382e585add9",
"d860ec15b3496f0e5870266a051e4de4629d7cdd",
"53cb8da8ff030a69edcf7bb73f57c22b83075beb",
"2df32c0099a99f10a6716d427b4d2a80cc2139ca",
"4c1b7fcd80384c77563f078762c6fe20cf0598a0",
"0855af00a9449a1566603780626cc9cefb9fa1cd",
"9cc2c869b44ae3b03aa466e05314d427101473c9",
"001aba0d292f1f5f5f334dff8e3d75bf709fe329",
"02318f199c6f29a2eede1f282e1f9b99927d27ec",
"73827f5362d9b1ade84c52eb4da1ee3d1e9f0072",
"7c016f9219d5d5d32b9b3dfe213372e0d62d4d14",
"d5fea6324c8df3e25da7063827deb75a5828be12",
"af3f07627b05dac4a68b102e2908da23b061a631",
"d98033a1ff2863b1e1d16b31a6fccab87ebdf7a8",
"3168107df942dc71605e4fa25069569a43d467e9",
"75b665ff3af4c29c53ad6979bbb93b8635301122",
"47dc2c562ca5f6566dd357094f275d7bbf014064",
"a46f8eb1d51855e2e341c2026d708d68f56081bf",
"b8a6e1a52fed64aaad86719a2f1f4783d778ad36",
"cf023f750dee2681eb73e4e0704da137ea2195ef",
"352c29c23ce2560750369aa50bc9f43bf3019d3f",
"a66d44ebe273278c4acfa39c249bbf49c1d38c1d",
"4a5a51e6e550456c75d1a2182b0eafb9c3033ec0",
"58305cda321859656022770c86839049ffb8c3d8",
"c675683da924026ea486125d71ecbb858adb131a",
"37d4ae4a9f2527a6f4922bf10a68b49ba67b0204",
"f9a62e7d8de906bfdd557c28fbc0ae00d879267f",
"dc624ed518ca6bba3b1a7ec63cfd9d96cd8d642f",
"45abb881a3389bea913ae10af32fb837060787ab",
"93d2ed8c61694ace1a085ef0c3bd8e4b950a2cff",
"7e5a1ababcbf3885e4dc8381b158e19190b29bf5",
"0c70e171238a7b3a56d6c4f275ad79150753f43f",
"28c8c1531ff5797c5877f94e6756cada530a8e0f",
"0ec084fc232f0df8c1bbcbb89ce8394e8a81d988",
"6d0c571ea9998dd98bf10cc191848029f5210d8a",
"c268e809e9dafb9f1d2879fb781d501dbcf61902",
"11cbc2e5154a9a422a654ab3237904261422c196",
"7ccdd4c810355ca2fe50243f1074229ccc191032",
"32d77641ab07c1de493d58bb2a49d2a96edddfec",
"f7e57361dc441eccb1e1e8bfa3f0660d6b96d771",
"8e331ce18207d11345ebdf7336ab14aa90a27a05",
"bc1d9ed4957b3b8e95184eadb2b83c121df2c297",
"83f26abaa0b5257d36459ef2aa7029c3af0f678d",
"f60922d125a82561dcb5152c5522fea8acefd8d0",
"961301f643fa0611cb43693031a30edfef8e46fa",
"a75db6a695a0404dbcc2afa83d0ea6326176d737",
"fec8a27a3670084cd98bcfaa95806b1f7d22f617",
"e359435040781d8a42637c506cb6def95a2a8438",
"7533db62f9dc43531f27a564fde197061a278672",
"1f80eb61edf268b046cef3441e26ed86bffa289b",
"d41ac59828c9b55bb06184b6ecceda30717be561",
"23332fa318ea9f6ce58ba75b3d4ad4dfea87ed88",
"5053a1aa777d4777ce2e1f4780c34a777d393e66",
"6ca129235045846ad1dd644a0ab362dd4107a7fe",
"3c8952500303c4626050873cfa8f28a18995f42f",
"d1e19a87b019803cfcac75e2678c15531be34404",
"3ea61f0f98a00df1402e489c4be70b7a31af87f7",
"e404f1038f461264f9395742ef74f5b710bef54a",
"9bcdd353c90f42a159b19045d02671198670a05a",
"5741bafa3b9149a312cac686247972010e115dc2",
"990e22acffbef7200668169bab735decce556246",
"5ed1b8e5791a507b242ea596770359cc0895b219",
"e8f9d21be3748ddda31b2b2d2c0ac84db49e31e5",
"f20c2f215ade6aa4c0cf4a9161f55790ee11438a",
"6cfed884bf37cba1e0d8e97fa8b0e94df4a04b1f",
"93578340d1d55b7f1b8fb31a8ccfd388f26e3ad8",
"f8fe296ceb98a1d2d06e521bc879176c56308a60",
"8604d3bcc7f32542c1c72e78295b5ec697690ab3",
"8d90699c302d2681d1a5224ffad1d662fe59a2ce",
"38ca038a0d695875bc6ea73ae88e048622dbc846",
"c1d9f0496370e90ee3a300aa96dcf21149543779",
"27a85987c31ed3002369dfdc434a74797d07d56d",
"44efdc02f971164b53db6df6ce2c3bd4ab1b949d",
"b3f23594dba3011ef037d42bdc3f2c6dec030ca7",
"b0beef4391766d245370b852b0224d1b12efd198",
"e1b40653538e276cce67c2bf96b1b0355b92f433",
"0dd2f3f40788b31ea2f246ff4eb30eabe344b0ca",
"407abc6a2cde947a25ef908d8a43295501b1eb39",
"deaf77e5b429e4b0c3e02038153f671a00c1e192",
"e488ddb446659b5efd7b59aa4991dc32c92b6c0a",
"06e22434e13a79c27ca7eeabf9d2b6a05b3d2ef4",
"28824a312764bdc83c6afaee232583e07a8101b1",
"634866889f30736ef07839796ffd3482239121fb",
"d3ed4bb497560647d7c8ec9864d7bb1625a52a8f",
"ec1d754308cdf1ef9d8eec08562e55e9cb5824be",
"faf19af9de8aea4a24cda72f6f73ab82b3e2db00",
"cef0ff571d1530a2b5a1fafc37cf776b29751b57",
"d9ae29deaa0dc43db4ea0391d6604cde0fc192c5",
"80198d68b6a31ae45ea013bf18446e056bb141e3",
"b7a7f55e78f190218370de7538340bfe358d7430",
"0b3424857ec1c5b57d6778f2bf6f379685e7f073",
"72cf3d19190438bb5a44a737d34f540715c0442b",
"532e5a0de03e0d0251bf1b30fdd6ba7432c5e4d6",
"384c506489dd6a4cbf8c80b0370b2b2a8de7835b",
"dfd35480be82828713ccc3c9206b1273ddac35d0",
"efe10f95be9fde1cda84f0631ec8f6546ac7228d",
"b7cfcfff7597a2f3f6cf9f30a348c923f11abf84",
"f4a8908727515ef857e620c0090e8186f196529a",
"793f53b5f0fe2671e57032160faa6806d50f3371",
"3fcf2a86da18fc958d79fd8f435e7c7edcbd2c58",
"292befdb36b97e48c5112dbdd6565dd6316969ed",
"3e98589a767d9a17a3da90e52ae4abb198fa9ada",
"84dd89180a85a144d9c05bb7c9068468065b9e4c",
"f232acda74ad8c260bd0cde4506c88e2d09fe112",
"d8ab40777de7c08d893b1ee0b97711b49e24a124",
"013da67aa1cd72776ecae5643fe5f055154a334d",
"f7af91819051b898bdd3d009791ee3ed0bc0be18",
"7d6d2e51d8ded989c1bb9a88d1df706a33deed35",
"3780f908a28f5f715a7c090293db53d45ad3cdc0",
"60798cdbc3960e25358fc31c4a7451df78d38968",
"86b7ef23c64811b4b07fae83d22148a5e78a6d28",
"191c287955f8673ce664fdfd7a88cbbd43f2d30e",
"8ba3087cb996d38b84bfed4acdb568ea0457ab91",
"10e7b94c304d215ad4a1ff326233098ab182d0b1",
"ea562215eaa163568c3f1061e4cbbd907e9913db",
"837f4694df48df27ae92966329b6a26ef9e902fc",
"880634acd4d5bf6f0182d5718f2af912cbda17c0",
"633059040cf1aae705172e7dac24c1fd863d44e9",
"cb7bed55622ad4ae3ff3e65466abd48f5e994a90",
"3c3d81a085da1911d69fa3d1d845f58dd7511178",
"b25d80d2729cbd988eca76bdfc5baa312426f1ac",
"ac572e64e5029cb1db16f05158915b6ef55ab7e7",
"ae39f24b5882c280c5c9608ddab43722c36ddcdb",
"0c513e981f729d11dc7d3b46cf70377f4c972204",
"8c1073b9c951edf01f12d3fd194ffb18484be2bd",
"7effa7c64c63637ae53c4a169bcaeb06c2205c4b",
"9689de9af08d61ec1134269d3d03a72465767416",
"4dbb022d229fc4b0170de9b497837943d91af6e4",
"8e7d193202991a5f4c944f6320cb906ce7e865fc",
"7b8da0e72f6a6e86271358173c7603d2b2891eba",
"3992d519c3248bf8bfc2f6dcf972f6179d410013",
"7c89045ea0617d8b42a9e0291c5b4244b9e1539c",
"2e77d5ef4df526a8453d38d6d2d735fe9ce7e423",
"6d698bb79414f1bfbeacda9c6ee352a2aae1f6ce",
"ed5a68c1d74a6d29d1206b48c80e61e25560a51f",
"59e09078bb0f4fe93e18a9877f18a075f83d517a",
"5b260964cb60b5f2ab96e823ba6567b4ffaeba1d",
"30908dcf48c1c0b314adf273a0bc08909f165802",
"ee041d8d063dbb36722c4beb6a20e4a6dd36df28",
"2149770a4b93ac731a025838e44e4c45edb3c3ff",
"31a7d3bd3fa3803fd4b37435f091cd39fc2dce4a",
"e40fe86ff8ea92dde1e53394d16954b833f10195",
"a163f4e9394d90bddaf0ba54d6012045489b1567",
"5caa7b302a7d4f247aaa7cc688a692aac4486464",
"9bb136105c587bde745036d858b6150d15cfe8c7",
"5cd016b587a2a90f2321af41122cc12b01b7f391",
"0095fdc58557b0c195ed97ed4c7e663f63dfbb03",
"9954a79490ebaead25c1789157aaf5b923b66b9f",
"9c8ab7fa627f7da7235c6f0b04e5c607640f0a32",
"d9ce078d5617f563af14396dab206b11270061d7",
"474b97950bf22458001edb25dd742cbd96d3714a",
"ee49e28766ce7c703b95e22d177cce046072f03d",
"6fb1ebec455c28b5a07dd8fb4809d7c7c7b8fbaa",
"753b7aef93e3f8deb1056aa6946cdc2fdc87b9dd",
"4787b53b1e85d8052744fc77e4160e4d90e46d0f",
"8bc578bfa8351a47239ab6b7c9f2b4e667ea2de0",
"01f9f3fcd48e0908ce3bb388a09a34ae8319a1b1",
"80bc95269b11615e1dd0f6d216f5dfec525f0f62",
"f1c7c9860716e5db88f657c61d39d6081fb5645f",
"c7bff28452b9b07c65576634ec3c223ea08e0126",
"675a0f81d93c62e2f4d0e1a05289c45a7e519201",
"5a958b5ebde8577fe8541c4d189b41a0649babd1",
"22720e718bc8199054cca4c11f23ece43ab15b5d",
"5887edf93b495d6f05525973f18885c653181d1b",
"9e1d6b1feb2635cc03e07443f564f0880b540927",
"abc963f2f27b2217889bdf978e3964d9674fe073",
"731688d3f2e5da49cf02624ea3332a0b3b430b35",
"fd5043d57221dba62eeb737551da17a9dcb758aa",
"53522288c15cb19f756cbba02f6e34714f6fff85",
"fafb3493dcf8881bbb453474d96481d2139782d4",
"ed8b086045ee5d7bd1327f579de7861a1cf49e3b",
"0441b048f93c67e4e01d0d5e0292bd04bbad72ed",
"ae01a424349795da1df36c732f215214e52ef590",
"ec22c943216dc80ace47d8b593e8dc3948bf74dc",
"9f62a82b0bf277ce06b51821d6692bba998201a5",
"5fea9ac05c7296dce3f8dec363b7442bec929c55",
"e56311739709570ea38f2d260a3d2f5411e5dd23",
"9793b4e7b6b1d20711fd9aa088f0969bbe730463",
"e70850cb36c5f08d2d8714017d5404dde34deefa",
"6a43e83dd66c83cee523b612805e4e6b5c0485a3",
"7b00bf2e3ac5e83eab262182bf51a5ede656145c",
"8dd17e2a608deb2b67d1e09ffb7685b929ab64a5",
"7d1db6a0131e560589a4b25f5d472fdf23998a67",
"8558cc2233b20326dbc5e32c966c0a6f22c8b53a",
"3fb04623a4a3950a1420b03243b40b72bbeffb69",
"2635562c92e1dbe2016c78087cd222d6276d01c6",
"8afd55ff6f46c404d40ca75a80c962f15203b9e4",
"d2e10fdef64d9a5c9fe9708746a85980e456af52",
"19210faab807e9163feea8c4ca2d3fe99e00a011",
"86472fdccbf95d08d0184776ee1ca75d01caf2c8",
"f542df1833d01ba6a50070a5b25bdbb9d575764e",
"20663a4e39d5ac28ad943df12de1156e76921991",
"f9ff484c9e049fc86c75e27070290ceeaa5a3716",
"43246fe6c87bdc6c9110332c717521e5613677f3",
"ef27961866b4bed092de9c58dcf2c0584aff5b99",
"101fbff8094bb6665963b5a819f0ba9ec2abdc6b",
"14fcf5067767ff7d634d52856ae6a08b6b7a3f82",
"ee9e6de5f347eff1e0472c2aaa30e806c38fe03e",
"6b9ff4f99e62105ea958a57b96abd5f1017fda10",
"fd93240b9deebf9c5ab551f145cc1f0148ff211b",
"86ea33b0ca5c6451473cc032a1b9758da7886394",
"766e281d3928fe35da422a685657713cad0ea339",
"e528c40a07f1a7d1ecfd4808b5a7ef8e5fb8bb0c",
"606882f01f6112de2b4dbd478aa92c83c428f101",
"354565c5797c2d9b4771d11f403b21839261c3bb",
"4e6746796693db9668eedbdd85a3eb61ab6a6ea1",
"876d22b072f5190db3b6c28208fd9cf4920ebf3a",
"550fcccc270a3f106b8a9ce01eb193961f35ae56",
"897404164bbe9879eaa0f05e432a9d98cffda635",
"66adbffd615bcd6a560213f01f3a35c424714c45",
"8fc37e3316e3861c2a96009f480cc92ff9412f69",
"ee9ecfda76ddb48a64c4580bfbe7e92537f26f03",
"153a8f9fbeffb3f688e950e72b8b06265e9ae5f8",
"11a109ef41c202603e774fb8b1c3ef64777263f0",
"379037956a6cb88cb826a7f57276fca4a2c6c084",
"a0f6cbf5f1791cd92e62710a0900b5aa6f8345a8",
"0a8317c35f8f0153b851e1fb214d87662be638b8",
"11e8b89b207ec5f6ba51c66e1c369c71ecd731f3",
"646d4360e7d905f0a9ec87d32c6768c5390eabf3",
"2f2823267673af9e6f04a7a2ec32ce9784db8007",
"8554e996b8db7066bee699b9c25a5daa12b6a1f8",
"fbef60eed63cce236728f37e4f461bb2bff5e035",
"370ae3643a57f20a88aff512db454f12ddefd258",
"3f489354b6cc5a8a88c1ce08cb60ea8a26d939ea",
"9c2f97abe19d8761a2a0a7a7e9f37fbaf5f64dc1",
"4bd45cdabdbe86c08fa9e93186d1e8d6011891be",
"016cab1dbf40578207a16a9dcc9238c034cf361d",
"fb458537b458664dc8b43ea9de823fda66d663e6",
"41a742ed9be97ca9d4279b4e34d8006f5675d34e",
"ff021d58897db7b927f1b4ba20959be013137961",
"11fc98c9c9c4c681d265e765df05c2f9d503ddc9",
"f00d1d67432882bef11fc940601f071efe55c88d",
"e1af550a0907304c2c520d6a49fc8c6185996948",
"9b7529baa7287c2331d0424d79579df92d145f57",
"b301fa6a008d5e2b1f57f08281e37ccb55855344",
"79505fa905e032629fc8e5bf9831339017e90817",
"1a3fda547a206ff9faf9d7fca331050390530139",
"e2c476a387d2f5f682b6e00e3dab02433e7000a3",
"2127782b742e40cf4e604d6443c55d5da996a6e1",
"edd88a59bf1f1ff39134c81f7e0aba7258ebbce7",
"79d928551b56b9094d69268ec78d8bf778ef2f2b",
"4bf3ab6fb8a4f9c707391a1dba31e4db5233ad66",
"55cdd880bfee08124d5b6a38cc05036402c7ab6e",
"19c484e956e6c0339c4cfc5ed3830f2446d3d1b3",
"93388e366c85ce151febeeb7e80c9c28a57ddf61",
"3036509e420846c775a906b514052000cd2e987e",
"23b9d30639ad7dffc18096b26bea48d4277137d0",
"29a95fb1a6f606d05b27e52fed56a0ab26a06247",
"ded0d19d59bbdb5f3824e58b08885b5091de20d7",
"bbd1e2cff60cb8086617251adc0c41d0847fe303",
"de38d97418458690653172cc88a881b568d410b4",
"819ae5fdf52d1c7ca35dbc4dc7f0832c8b271b9e",
"bc4a13902ca80b1c496ab65670c0526141663e9e",
"25decf16175682bb3ab22f05a309d02bc4a22bf6",
"d7aa2d9da2dd3144a22abb32be582df658178def",
"7d2f0e387c66f3f24b94673a2de9589407e2f946",
"0d96af5d07de3fe52c6d70203f77176aa4f4cecb",
"c38b9d9e1eef6b9572cd75fc131c9afb18bf6df6",
"a8255a2e074aa07df5fa4b4fee5a3703b8d41d94",
"690f6b02c0e0d9201807e5711b0e6c6f5a0b5c5a",
"119a1248979564f85a4cf42c3a9e7ad918557d8b",
"8a66e4d04492e3a3db410ace03ecc39e79dbb45c",
"192cc993a8f2a31e49608e9aeff2ecf04ce602ad",
"a568e7f4848729ca02d5d5373dfacba289658493",
"cbd2a7070c9a8c18ad20785f383eb1dd0273a1ee",
"a8426dfdacbc4e896adf7cd5d97be79d976ccf5d",
"c5b99db101f251b1b17bbe8df5885ed3a1c16409",
"a4d83ec8d22a80a4d01381a091967b57fa595018",
"fca96e697f128837b00bf950ad8d556aba29a3ad",
"19a262d3d67ea92a37ceaf18e79a783d8e65ccdd",
"ce11f03fe63b458c38c331e1c0441b3967b44fc5",
"fd34b680b59ed99b9e1c1283bdbfef8d779efaf5",
"5229fb8a597240825b6aa99001a8079bcc0264f0",
"31039bbceb6e2732f46f070854ecba810c6a159d",
"d2517c5004e0d442a365ae66b58796cbac41a926",
"a670b6e668761ea5893b7d343b4515b888712f14",
"0c6ff06c65cb6a9f6f6ac9c97d4a1ab04ecf9615",
"1d7478cd909776b4423a90cd0bf40c10d711e989",
"2a0f6fd3c5588c0779b05d295b118cdc4adba9fe",
"044ff8adde36b0f58a15ee448895e1374d2f7e0c",
"c0ac228c37cc70c4f5a662954659d6043b3ca1db",
"9b59c0e2c64711d0355513db0bd445d2e119c9e3",
"dbfcf424d6149677524a06330981aba80dd2eb24",
"bfe8c5234f79287d23ec1ace72d59dc1dcb54e35",
"86119473b7c17e8f1090d52f79a2433089f1825f",
"8953ec4c87a4d69c92f78c649b82c9d009822017",
"9a7c22536b1a381b68acad2975fc136460fc3d21",
"c4ff0d8eae98a8334ccb2e668b646a9264a544d5",
"77f63c76dfb17bf621d5e8ca131f4bcab76b4daf",
"cb7c748c663c94d5d8ac1f5e1a5b682b1145f26d",
"9486e751f2de576620057781e9143a41b42eb1e6",
"787cb3a87294cd1f03945f0dd481cb32b09cef63",
"b0af48aa033166693fe9a985dd764db3cf2ffae8",
"0200e84aeaa2a507b6037875413ef37763f485d5",
"6a1b13bb668a1bf59579150b12c63d816078a6fa",
"f6f3be437bb0773c61842ae0d5b341d1e5305250",
"b49ff9e5af6d6535b8c0a9b04f8f968d981af921",
"1e66c576434abd1f121dec1eccb183542ae18c09",
"01bed73a60ab429c3f90a90bdc31a138ed54c78e",
"ed5b2659c8d67670627f95405cfa6bceab98904f",
"de78cf7874daceefbf6b370a31a3465e34e86423",
"c8b6a13d6475086826ad357a0644f5326a8abaa5",
"c089727e9058d7412c6ce92dc4a598bff19661a4",
"1cd3ad078453b316dc7f1d4aeb637fc2f6af35e0",
"efa7efacc401243e309cef37d90e8cd023381c2e",
"c15288a690416765c868f74cbf3dc4c7fe0b03fe",
"1b33229dd2d6f80cc544a3a5709c5355e6afa2bd",
"11156619b3017fc27c0a1942956a27dcb9f1c626",
"ce2d3eb07137e6c4e6eff9f78306869d7f3e8e06",
"ca7231e652ca7abd42dc48ebbc2a82c82a1b637b",
"685c84e5989ecdfb8ff87fa70c855d10f5305bf6",
"4307eb35b5f8ddac2a704de0c3475e2df072b359",
"376a5566c2918f75a75a8b4a20c18b05ba73f63d",
"84f11f5e3162e18357d1517f9468b742391ee3d5",
"8a6e55502c9be752978a6429a22761b2ba10bbda",
"d147094812207130b05dcf66ef79bd113caadce2",
"0e48723b419be95340a5d9858d76963e8e97137b",
"70009f7af29d1188b0f47aa909daba95d7c3c049",
"944d39424793ddc9e4f67dcdca24e7140c5b02d5",
"11d29b280ae9b1456ddd58cd9dcceefe3d47d60d",
"a8dac56ca645fdd98955766f07abe7cdd8980e56",
"d7b48b9e2986adf16a9a349b5359361e3d4b6c2f",
"b2a41025ce42bc4f9e6b405a00a174b5e0cd3d06",
"c7f3c47f9adf967f2886d066cfd0fb9e607864eb",
"2776e003dc2f7e585c205cfa966ffb90f2c43ff5",
"7a9d4512f99156681ca879e0794a6ade154af33b",
"5d467418be7f19ea4e4da71fc132c0b85642f585",
"4934473b86b3a014afca8e5317b85c0c78cc58d3",
"3d352f23e6f7c7170864e3f453f0d744ab85bd3a",
"54fd8c40a0b64e061d0ec4f32b9471b36ec11ee0",
"174792813aaa0d51de721c6dfe6d299ff7e03ab6",
"0aaa81f82a60d35310c09b518ffb283bf1bb1af4",
"fdb1ac4e3a01030ab4eb4415db68d5bc1c719718",
"5bab3f9cc02d6337e2cc9eb068bca60e6e7a91c7",
"906803378945c2272a0ca381b03a8da3ff432a38",
"586eefc3e4175b3fc27189c8223776248f44dc44",
"efeefd0daa35682a3ff07bd6c24d73248252149f",
"2a47bc0c7dd6238ce3416e19d2ba57f3a7626f64",
"a998ce691d6962ea75d861b25532f4c042c36f1a",
"8224819fedc74f81aff018b5afbe51f0248f2c85",
"1e0a14ddcf2ac8cdbddd3d25f5e378f533157563",
"8e6279a3828dfc59c4f5e43d9a16bd30421c6660",
"95b3303eb91609e9e959f4d873e424170c385d88",
"009436efac8cd5b9a59cfe92688cda6f17d9531f",
"0705501537d52d4bf1bf1a7480c3f25d98f164ad",
"08b535d56794bd378a73e491147c934550ac2d45",
"e7fb5647ac0fe39e04c51e1e19ac030637aa0011",
"70fb0d3fef0bec250bdccd58bcb6f4601adbe065",
"a28fd65e890e3f2088f8c8c06b165621e3bf9cc7",
"d46d36ecee7cbfcbd100d6970266269af87f6f0e",
"92d77f9ec373261d91a65e68c95baaaa9fc9b95e",
"37ea81766ec8a008420c43091364130bd61016f1",
"85ddcace0a9fc888aa05bc0e8519ecf8b8a63911",
"7c4b71ab8205a69a04ee9e9242288c864e6c7c33",
"1fa30e2e88b58e48e8fcadfe416b65a85f916b4a",
"afe64d517533ea86dd10a9fad82da55821236127",
"14444a43eaaf3f0a446090a698e7be4d809f424a",
"a9f75d47ecca159383fd9df0c3a140f8c063eb57",
"da72557cf70313a5400b62a9ddd45493da28e52c",
"271ef497d78be91751f7c672798bfcfbb8312838",
"0e3f3f03d2bea6764c5f63667f7aa404dfee6708",
"010d5134e8fae35e9e4f179d2929e41a20a93d30",
"3c5668edd22ae4b9a085220d6be552f944ccb038",
"1c20f64a26641ecb7777567b9661599d92757e08",
"61c468778a87a3a40acfa3be90107cd98a1451b5",
"b9759c58688a1fe63a09c92c43eef10257f4c9ef",
"408d4f27e7ef6a56ca1998802c4e8feb9da991ac",
"820122516675cd6a2151dc459610375161e40534",
"ff365e2d8b7336108144332421b0b72e77ee2ad6",
"a69397386a9b14021f9859229eac2b83aade0139",
"7f646666bc9b830ab79c717bf541a6c80383599e",
"af6cf03acda43bc28ac7de854ec9a4768a06c397",
"fb8681f5bc5460a7970f023d61b272d0a1474711",
"29043134a361aa8931cd069a1c72e3d2e8deae97",
"4e08eef8d5a7c3eacf18dcd17456a2d48809151c",
"3a47003578e33a1cf6dff40885325bbe66bcab35",
"b77809ae9d41d09b4f3053e2c35a723c29c2897e",
"fe6a11d0db4e8547c0bbfeadd91f7563f5098f2b",
"4e429e4408293b6bbfb0909e07cd48181d5dc874",
"34939253f77c85bcb055a0d9deba6bd08e7f1b39",
"c30298fb8a9617a38013a91ce4ba433392b90f16",
"e965d9a2c98e3f93d1a277da2f10c51066094d8b",
"db3b3b05484029bd747abad04911c405551be1dc",
"5a840983a8ba27f4fafbfeb82d15a10b1b9c7842",
"9e010068efdc4314dde2c07386303bdeed12b3ee",
"38ff2652b1290cd3a368058e4be0613975f20de7",
"895ca5d025fb63d9fab854ac4fffdcdd67ba6767",
"76e00a34ea58c2d424347323eba4623eb487b19c",
"84427a56b5b7775b1f48254a338e2289838696c6",
"ee8ffcc79961d34a88ca0abc2268a23959e2fe15",
"ec47566cb0af0fab62e00a65fd1f5aff7a867e79",
"570bfc3bbd7692f7aa4fa28fae0ccd5c348b5532",
"deb823f3b3bd6ab3eec2652fdf18932e3f160c63",
"e39653afcf8a1d3d52011868e4d781857f74c904",
"6f34124d430ffecfbb858b7136834e6006da8ee9",
"6686f86c6724a31df43aad6d0f3b3a6ef5137000",
"d8d00666d35bec88970508a3f3d9093cf6305dd7",
"42285e71cf538852590c02f3f5b8f05321013bea",
"78ba263d0a946c4b90235d562b56ceb7badfc965",
"af35e6f4d04735c33cc10777d6421a61555db754",
"727e4e72c7c32450a3fc28bd334d8726cd499222",
"1df8cf102f1a614ad24bd49437402bb65390f204",
"a354686bbcf84ce88af5cb41b60a92734540ef8e",
"e30e66e009393ee4b25692581a37f42320725085",
"ab62dce683c14b53630e4190ade945ed082e343d",
"b2bcd561cf1e2a5088cf600b24c9ee567bfa2e2e",
"b614167bd90474d2e7b503a4986c505e790151d7",
"6e9517a186b45b67df022e74b2d7ef7254860c7f",
"5bc2dc677b24aa5c266957fd07122b81fc85a683",
"6259a70327041ba28ed9ed0bed3301f2fca2c92d",
"eea6a9bc70dae097f8c1bf22d94cbd9038cb7238",
"d50df68b742729e1d8a53e9090b0d4f78f0d6134",
"3bc0db68f4d306b1ad599efe7d627151d0aff382",
"0fd8c8be4d08d61505e4c693ea062803157c670f",
"bac719da218be4736959687af8e66ab35d860f3d",
"9d4aa59a125228c4c578a750bc617acaab1f911f",
"a8ab718b9877a40d988dd2aaf21a0891ab210978",
"7380e2118b52f53834e448a04969b2b849b0b4b6",
"eceb7f29c8e86dde959f205df335d0feaee44972",
"4cd0782f2e442c76cc433c292cdfda5523d70bf6",
"fcd1acd1dd927d9df372a8dc47332d0ffdb16820",
"05368e84fabb0fa5d2995741de87374812ae501c",
"9dae540c8718f1d2e9dd26a68cd76242a16d7eb0",
"6f25d73d3df062e7b49df4b2e9dd7cb5aa3a98ca",
"e9cf91e1bc9555c6b9cf7e6f88e6c6a93f61116f",
"e6ef767f36e01ad0e8d75ae2278117a83d0424ff",
"f4c8ff7a64e87a173ab2f114f3a88a2d475184ad",
"caf9e241a6d50c55f266c07e818499066b0818a4",
"ae1165fa587b17554d6ee4b30f244cc76ec321f8",
"edcfcae78cc58e6b85a922acde46ff4eb3f5b6f4",
"40e9b7ba3a0d34c5f07225152d12d9479bc9d164",
"7dcfe45781fb94a6c5df4991382dd3cf16a296f4",
"924b93283c5bf37bf7d414d1b37cc4574f527fc4",
"d1ba665ebff82bd86b6693e4e6592dad7e35b797",
"aa7dcd92dbec472d7aa053e6c7a417bd35a13b62",
"5a0c14cf61efaa0cd30880a7e5667b4ac2c96a4f",
"c57d43f2f5e8b3b0320364062a48b6012501256a",
"5b4cbc2cd87919020e7c4600f3a1c0f0c8fccb5a",
"fa9c6cd142b4763df5cd5e422074a44c5fc84f3e",
"cc96b9ed7d7f561ef0c6ed22ebfb99da6e2e2848",
"059c80458897e5c678611e22ed34b9531faeeda8",
"1a67ac18f36045fcdef1caf11204df93d60b4c1a",
"eec4dd45054b7f4be1a6ceeecea9a9e3c53e210c",
"c205322c5630baad4da3f8368502cb6195941211",
"b608a7880695a2e21fe25240238f0d26e13a82c2",
"5a2f26eaa7a18faf42ce6c0d2e0d0da3b9385491",
"ee12f76cbe013b9ea891ddfaac871969563afbbf",
"9988b63bb204496cab00b584cca60ecb7beeb036",
"1f4fcc5e6a3dadef99284bc3845ada11c74ccd97",
"41f9048d96596473600e6c77f041d29cd3de1d6f",
"105b65c2ac2ddbdc75013806955c97f3dff5f493",
"9f2c4e39419027a4113e4e368ceb81176897b49f",
"5a0a334dddeee5eed68ad8fed3b59213505675b7",
"e0d18b86561b20b3789194d861c3ea0b183c9e41",
"98cf054b2c991ba18176a72f69cf219e62cb5e96",
"f5fa84fac6736d2e31ec20c9b844ff12e6414d14",
"59a1021410a28b635d86cde34da75766204f2f7e",
"5553a147523778574c1671d4706d34f723138632",
"f30760d6bb86d2978a5ed4df8ee45b9aa97778b4",
"e4d23fe56a7f7329ac98991bc55bb043ddede617",
"547614a5bbdca85e1cbd205b37cae7e25ba01273",
"3018223328d566c003e2bf37959302c6f314be42",
"6bbe919c4b6ab9639b1130b12f83457f9fafa61c",
"a90aabb1fe2c5d6d969f6c3236f45f93bc6bf3c4",
"f13afe491d169004159a033c4ad7548a7ba76271",
"6dcd56275e606396ec82f4e95fab1d736e8152a4",
"ce8ac663f7fbfa3d28b4677ea28e8b2d47d7a032",
"a9fa31e5e6c5bb2aabf8c8632a7e61afd0204d1d",
"cbca3af260a53b08fbae3864a5b0316aa83c7e40",
"ce07e92a2e634a657a5a6b4324642accb51dc89d",
"77386b0fcedd5bf8f7f9af59dfb678f9a07beb12",
"10daedf96d81a0795756a5d0d4a3e374a9cf7c97",
"8fd044833e40440e7b9d7a2c08281f404e5f5ed7",
"433483e07aaee791c3c7ca6e9ffff1f24060ce26",
"dc1ff882c5fb734e3e5cc6bc0661531c9323b305",
"72913b8c152e588e14f42aaa851df9de642f390d",
"96637aca7ee004620e35d8d495b33e6601270aca",
"47c785b9160c31ab360e15c7b2f849e5225ecc66",
"c05434ebd5a2335f432db9ac1820f3e4ba181e68",
"2af090ea1eb6ac806d9598f657c60c5327c12143",
"7eb07e1b4d57ddb4660d0363691877fe893af044",
"13ba2ef0fffae80451b392dd7241ef352a700c40",
"ebc8d037d9ec4036eacc4210b7e13109962948d5",
"9abedf449b6720ab7c156ee3c4c40ad4d0165423",
"538648c5422bc8564aeeaec2d50fa8e97f99232b",
"a5665412f67dd45b6557e83db305a0774a83c224",
"9ef9c5d59a8efd5e226a236b82ff14b6443a32dd",
"c847a16e141a57a803b270841d5af38ab56719eb",
"7de82b5025f8c314a85c5f999c4a04123b6b160f",
"6940ac42be4e37929d8937425435323e49b48ce8",
"3dba4fbc91dc7f9cf9b5fd01a0d62262be3f4a6d",
"dd5f7396306612665babf751eda5d472470f5496",
"170915ffcf61406aa1239555625152e6b0649111",
"c2863c08ab58e1098ce29ab99d6d3f902e42c8d5",
"a9a4aac3229fccefaa4f3927814503cd60fc3ce4",
"a723068246bf5ab646efd25f5b9e0f0d6304291a",
"ffc86f8a9687a1a085f955abe058c7f1cb65daa6",
"3b5fac178eaf9bca639fbd0c1df0c68619a7f51f",
"62d000f7cb8c5dc7c8be482fc1e3a81b4efa6689",
"ee0d19f2eb5744777ed717b8f8ec585e54aed4f0",
"4cced3ddb802d04c982d1833b8bbb39621b93228",
"7d28d1e648b58e15a23fdbebadde648b4c8505b0",
"dfe89fb3030a0e9be9c538c4ff25281c2a4fda70",
"a1cd0e2fdc9416a6841e15bb1075db0e7a99424c",
"f0390e00d9e1ef6de22d057935fd16757d9229d4",
"ffbdabe432feb66edcf7cb56b1a27c22736b64c7",
"985987468d5b84d5bc8257bf3b9166e89deec203",
"7c902b6905724345ba850eb6cca8f8becc9a9c72",
"65982434658b88f5d4ed4e93bef3964e7eb5b645",
"41c33901ff6a70e87e649ba61c5d52c84f661ed1",
"c8062bc4a7cfd55d73dba08f03986ccb2f4e27ee",
"4c82bb4c4ec776e9a3e52dd294b22834a6309d32",
"2929146c49c5873aa522f7cd0fd46a447efd4705",
"b6cf6fea8d6d4528baf52afe626099791c37fad3",
"87cb7bf52da9ea5def8fd6ba80703dbdf5104d21",
"87f6956e494a49d7adf748fe9ad53d7984b8ff61",
"d274b28ae0ddabea8199988b38094a25bd743d69",
"d9c76893a144fd787654613f2bfb919613014a71",
"19bbdbca241473a9e58120c480a2338ba2082a36",
"7ed72ec918482aab0e0409abdee0d1b0025469fd",
"61865b5b5ad715e2b812087947281f0add9aa05e",
"8e2fe6449ef83462d05e59d9d8744a088fadfe9a",
"5fe3d5a7ab6a6b6b3163bb9f9f9f3ea1355c9983",
"7616dcb7939da1c2db260cdc7ff4b3746bee7300",
"8865b5596e7c3a154cd90fe171d373139fec8636",
"289e59bbfa3fde12b84a7021d8d19c61f23e3a2d",
"b4f18f43d3c642706038058a67b70b8bbf1dcdac",
"1fa1cafee91f379eacd7a4b49b9de1a0f8afaf3f",
"fd892d006ff0b107533257b1427d3781c5586588",
"70f0cc354dee34fc5efaa593a4166872f4089097",
"f58af8fef4831d2096ce3a083e1d33f1988b2eb2",
"bcba8f5a210999e73d56ac0878dee1c679cd48f5",
"47b200988c311d6f06bba7244efa829e9d79b637",
"0ecdc764221fddf442c3e019098dc6f09697ef6c",
"3ad84420bd882f983c2f9b605e7a68f5bdf95f5c",
"2d13591ec21e6ce04678e2965f08d145cf2d76ae",
"a7e96131ce6e9effb304594ad7e7b9dac486a2e0",
"259adf7dc215f92d1e039d655a7cb4e587055aaf",
"cab56c1113e74c896fa27a6c0991aed538012c1f",
"91914d9345e75fbcc1922e5dcbe1e0da1f2c21c5",
"e412168be3b005d53b20bc228e46cea53b317fd2",
"159d3fce93024ffa9b97605f768e9a116a040cc1",
"6c8ee4330ea04286567a20880f2c5b76d5af9da4",
"088339850b8a355b954a26856a8bcbf66350f44c",
"ccc0297b5acb5a375cebfa7868dd9b891462fe03",
"43e08a8e70700168767672f80225b19396460122",
"c6d975799ac875b200da804febd982e462544ab6",
"f9c3523183efb8f789f3deaeac2babd23bfc536d",
"0d402647cb2eb98e4fc97c3a60ab3c6cba9152d0",
"23f8cf0d8484cc8b605d47eb32528e3f964d63ef",
"df44cee9ef009fbbb4a7d6ab741a8563c34ab139",
"eb095c109b176eb9594ab5f99881bccf06213459",
"f6aa46a283f63025882551a27e6d2145939560f5",
"11a6ec5dc66082e41d431f059e3ad35559c7c87e",
"0bb0fe8f258194cae4bc4177c36f177f20c2d467",
"6dcfbfcdee6df013656b13afac3c765ee314d129",
"09f796234d76f4a25807371bb709c18678ac7bc9",
"0c9a7419dcfd265b6c1efe85c915d126feaef649",
"a838c3ea01dc0741b22236c9d2aed7f6cb0c1d86",
"b4f2614d6c2fefa2b8721e815d63323697a9846d",
"de1958fab04a95f73b7d7dcc62d66775d0854fc1",
"f83c11674287d4f56c43daac74d7461abfc0ddde",
"989edacd564fa658358f5ccfd08c243c5ebd8cda",
"24066c260079b2a4bd282f081c3d5a079353af34",
"46c2637f777d1629bcba515e302dae96866a060b",
"6763bf31e1af93e9b6ef72ad99c47f3b9359b7ac",
"855327d303566aac1d3e065d4ba7e16d9ccd18e6",
"034eb418600f01ffc27b84ad399372410d49cd13",
"3acdb17b86c2eb221efd959ef5ab8ee025e6bd12",
"729a6e057ed1f78be62e1da0c98993226b1527df",
"e130b4dc06ca02a035519e1ea86ffeafc788866f",
"00639182a7b7466f9d86486f521b26002f9bc682",
"47842a81e322234a8bac471396eacd6dd8928a21",
"4b955fff15f5c02aa1401ed4fbf357d63f2ea21b",
"f244d89e56f8d860d1d55d0e9031706fc0c6f5f7",
"1d57778f6b9a5731fa802d4f07b497938461072e",
"d39ba83cfc7c7685548d18652fef039e25b19276",
"b77bea8e0966fae1b83e0866a3ddaeaa4834c926",
"1c620a28194fa85691e53a506061f48b883e8777",
"57a0c8c46cd01034c4b02df79a39b1eb84ace57c",
"c8b33a4fbae90f146d5f23e61668655e6400d871",
"bde68ac76ce093bcc583aa612f45e13fee2353a0",
"bbc79a7e30f5130703420cad6d869ab99e34be89",
"73467bde83154717f434cbd51d16be04722662cd",
"bc142296398cc6686b68c4aef652046a8eb62aaf",
"4e112aaeaad8919c10f0a30c9f43dab541d653fa",
"2d241e5f7d9d4e4a5be935c332abf0c8f30077e8",
"c112f3fbc98d7166c0af37f83d1448578586d47f",
"c8fbcf2a7aeb0dc8b5c2f709532ae464fedc3677",
"0dd06b91c1ac610a94f9068651f1a133d1b13bac",
"621c5a45631e2f1f77a6a2bd27ab418592346866",
"b398e54b831aa0427451fd068faeb82c768dcbb1",
"757483f35139d6642ffeed657ba0f88fae512674",
"8922388caa8ad879bdc2b82267bb5122afb77a1e",
"c0aecbac3a0f5daf90f8110983c81b1ee1972090",
"beac36705642884fd769d71ca93b322a8beb93b7",
"cae66b6168348c2c7aae9d95239aeeafda13403c",
"f71da0ee9596cc4409ac9d36c0912989bba7ac17",
"eb432b9bc1324d05e3a6c2a1ca6d2c077542395c",
"ab6ca14c889a0bc850a1efe80180854f42670f54",
"86a04439168454ab7e2ca4ba69b2337d581c0ce0",
"e1470fccd7c84977234319b320df54acb162c9f6",
"a61affa9fb1d4a35ae5d8a6f21202be042b7e8f7",
"1d1b9c3d49284be3e032f3682e2b12c27912b45e",
"9db69a40a62442a1c6959cdda553fe7a57105709",
"bfc949d094d9b9367259cfae7e20f32c9099ffc8",
"2b750456615b3bdd68bddb3d74df3adfc3bd2a8a",
"73f3c496892bdcf1e4d5ce5d4bf1ff6e77e712e2",
"16560950ecfab3c8b9edf19db4cb4d665e8472ea",
"a496190198bd5dc0eb741c57a87fe4112ba32647",
"c6a8a0005501e03573387065bc783ea7d94ee7b0",
"0e08452323bd771d722502a3695fc3c29a157d69",
"52554af4f12d9cb8b46793dbccbcf2451a5995da",
"468d5a46ee9d40ed98868520406d1b8c8b1bb94f",
"84e3ba1482af48e8edd76178fbe976a6594e42e9",
"ee1c867800eacea37d489d966622d0aff0af0b70",
"74336f961a5f6cfbb30f867a9eacfd5da579f597",
"7cecabed42956994be62e45cb24768c0b0b2391b",
"81a3bc3d1b24841b57bfb7c8c205c4959cb92670",
"dc34eafdf4677247b539ed5c0f83199e372ef594",
"1c46f19592d041919f18736cb45ec6046d7d3b00",
"a04381f4e5fdff04a2f9bfa15a16d2addbcbe8a7",
"29e681210b1e568770ed6fc4d5ee11e7d346b5c4",
"723e2741f54605c6404d0ff7f96cd6c14633cfb0",
"6f8d75a00daac96ee4b375b4a7e93cfb8988820c",
"123f7eb6bbb3cb3f39257b325b2256ecd415fbe4",
"1848c2b85d1bb9a12531b3f31a59e8b2958917a2",
"a831e18a72107abfbf11d2ba3c12f8467a345009",
"4a497fa66f8293c81bc7cb2b10f4653ad7f9f7df",
"189046bb5d2c871028ac0a0ece7231ed49bfafae",
"aac23dde0c5dcaf3861ccf6b78181b2cbc07ab7a",
"3c1c35f259f145d10c64abc6b006825c7bf8243b",
"27eff8095dbc95ed18d7e88e97367e744de6a398",
"297646412ad38be27ab515245066b3783d83736f",
"823ece875e48abc83c302ca2bee53dad16a8b2ef",
"795ee35f37c1823621525baa43f07380a6a911c5",
"54551b117435a006acddefbf3850b02d6ee84ffa",
"1388601cb627d4fcf8a401f83bd4b2b4a1436481",
"605388f850d54ff4472ae326199d803514e691ff",
"13707fee32d2c47ea60f6903d871e041429fee6e",
"d221095980d73aec186882799d884a240fa20e71",
"34112d850424f1978e9efe402dcc4c8d31f9ca02",
"a32c4b93e2573fd83b15ac1ad6bf1317dc8fd760",
"e56a70b0d36668ac60cc2a1b2846acf7974c51b3",
"4b65c22305ddabf9bef331a372971e0c81e0de74",
"fa19105f2fddd1b07f79514942eab2976a09d7f1",
"84aaf9efd08563df2d55ab5f2557badc0522ed23",
"54d23545ff70903cfa4e513b33eb2f920debcaa6",
"7fd9c3be8f2c63c673bd7f105f4672510de89ee2",
"b731dd1429ae70453518cb6dcd32c54315247940",
"a79ca5e8fcc211b6183bac3d2c3d4f52b106d07f",
"38592955b25c03f357460d71ad0d56e7188f03cf",
"92c9e21873be1c9107f906f826d4774a8a950d79",
"f7d8f1b8dacf0e17c8771afd7a1c4a1163bb183b",
"bbb292c8e65ec68428fae285b02751ef2ffcc363",
"0be7453e764e26dcc2a3a4f4ad903b1b236cc753",
"9edb633d98ef2cdce6529b598f6d33b6e3fa1a0e",
"765fc48c8496b35717a53405d745b154fc655955",
"c94ce020a1f7eb10469f3fe2195c8620bdcdf866",
"f8c6cf8bf9b245ab138f694236fcbff2213eb65f",
"6a9f11a1d9747661403b4a59dde8275548334e86",
"80f1e6516cfb2412988c72deb3dd024c2a920bf3",
"42ffbf3fe66b5d7a78604bd3c7d73f57ef9e9487",
"f26be552c20e8db05ce9e0aad9d61ab6e4e2bf48",
"6f91f2fb8fc29d8ecac9653411918ab48a6fc44e",
"3260046c67d03c5b161fcfdb148876e9cb9a0733",
"589c3756246eaa3cffad7ff07bd1ef07543c64c3",
"6598e7745640cd060616230adc18e122af49343a",
"0a7a9c294507f98c939ffc690e82f3e2080ce2b5",
"dd7a0b3524923fcf51f0b93daa598fa76c529e99",
"47c9f792e608c80ec4cdf57429a8177efcfcc73f",
"a1c9a927c28539cc0435269c3fa8121956eb89f0",
"484cf0220cca07cea1863d0e20d44827683da901",
"83786fbd80ee6ca9fdc19c32e5353d3439d219ab",
"82c5884fdc7620cd4b0828a89fa8402cac024b18",
"a89a300390115745d3a5ed2b8a960bdb3b3dca3e",
"76edc0c52357286ced937634e6dd022c230b3778",
"5c0d1b10e0c99e763b377b0098ef3d893fdc8098",
"345ca923801aa13f124526c2e6431acc5823a0a8",
"614f3e7b77aaf185ec15a44a2d2fcaab152070b9",
"f0e2018ac564746ad468ba6bc68c60b85eb804b6",
"fc55d67929ff7c706b1a0a7826ee7581eb8e8232",
"50379548c2d3974a5d2d8a903abd47ef5cc42fd0",
"81f94d0cff52fa750b66e8ee8fc17b126ae76715",
"a6b5c723c88aed4979708a7e7baf5a9f8681cc68",
"b24f8a30d65e194a23d4f233c57973399822197f",
"d9fa83f9da61b770b0798ba9f42301ff84e8c826",
"6966c971944a5bcfeef21ee8664e8a84a16b09b9",
"ce99f7e7e45ac22104434c6094ac2fe410a8970d",
"a6e33ec19a662e23e998347ec2dd2d3c90bdb7ee",
"a4989b7ce79590fdab3b16e41a8b6049fed3ed4b",
"ab532be0330358ab7582b8a40909d5dc1a5dbe95",
"dff6df10fb3837093014da692dcd3263cd0f3d31",
"3ae7e305bd6d93f3e92167285e2fe00c4cdef50d",
"cc7d0cf3633282ee0307ddbc20f7641c9deec52e",
"db98daeccaa08d2dbf2982beec599519be24f6af",
"0834e0fc7d3c2bca164c33a8e11818dc19a892a6",
"3075a399e9fba16700421171d5bdc4960561b432",
"1a8b2f5e2cfebf7ea9eb02ec681190eaa7a9ee25",
"34d213ad23eeef6b2803f4f3f88a83cad4423234",
"61733ebb9534ba497c2af774e92f78e359751ad0",
"a85e7f7442117271c97ffbedc1671a7b1ea996a5",
"90deb2040538b24721ed00ef1a0b81d2438a980d",
"3403a66d0fc9c9cfab97eddaf5adeab40dc3bf23",
"6d11ea17c88163ad4a5047c0ba4f7b7fd756e99d",
"6147a8a2fb16613c7b3dc2a999c4fa5f024bf90b",
"72dad241e2b990b826a4c5e9bd6fef09ca67bf3d",
"30c9b0db0ba5939c2949915c9f68c450700d7254",
"749e8239852aa4591277d946e585607dc4f464aa",
"d46b0b6d113ec86c8d1443c1d354ac7ce216f684",
"860f1dc8674bae9d92fe7311e204fe02e7bd0d88",
"22491b5994d587934916f0455bac258a6694c96a",
"191278f0d92418639867aaa13b437945d4162b6b",
"f78e5a4281a6f6c72ba42d4b972bdd2032cccf3c",
"9f36320d839026a95e8306637035762f05d36e17",
"064ece32ac0a0bd0efe4f459dcb0462bafc236e6",
"de434bb437f64b0ed262a5bb089c6a82a18312eb",
"740106d7595c4e2722ca2c8d0f6ee34f751f06d2",
"3fe6bbe1cfe220295c3cb376b504089af4715f31",
"a4e10f034490d2b691b3dfefaa2f1c83e3cb7c03",
"b2992814b61b19659c3384a48c2f98b56eaa066e",
"d839418c56560a768455fbcdac50fce4732623eb",
"d56d619f5601ba456c7bb517be96a1418743cf9e",
"8402b85ad9e646d96efe31d7f6b16d76f7131219",
"ca7db1620c6f8d4e9caed0902b191c5e6def8bc3",
"cb2cbf014a123a1cd0cd0f188f093e014f93647b",
"11a1bca0fc97dbc93653e53f0e33e7883f9cb637",
"d5045417d6abdb8fa96509be53c7310d7fbb5d17",
"0d00528d48838067d77309a3237cb559ffebb253",
"660236225e1fb9e8531129ad83f695132ce2451e",
"6dd29d4b500ecd3fed27f1f29b40e7836ff061aa",
"5727359319f2b8ba6311f066391b7ab0004e5558",
"3b342ab385810fd3e67ec1fb05f45b27ba50bc36",
"b195a3eb356a231d64981c789396a709d83a5d84",
"a6cb4d0f482ee7d611a59c6a7bb426dfa7fc08a1",
"72c715016f4b59a5677a4c97e4ce2c58bf9114ec",
"f038b7ee5caa5c776d022c9a76f4c688aabff898",
"344fe3a90121c214c3fd83ca44ddce56c15bce42",
"027bfbef67fd2af6ec1ae41a07b1b245c525d943",
"c8a24d558416661fc3b39e9dffd323b71a23f224",
"89627a8b6a58cad55267296c666d7c4b246e6c53",
"f0648c2a184732134e38f8ce1eeae5f6b2f5a04d",
"fd4c4cd0af8836213a0e846e674fb6554c123e96",
"cadd996a763b4490ef177524d21e5059820ff833",
"21cced05c1dece28e3f1320751320dfacd2913ef",
"25c6660a59c621de1ec406e4f9b2ccfbd21e1b90",
"cce46a3d8ba1bf2118da028b4c14b518cc03bfe1",
"8e541dcf58c52902b6aeb42d37eee06e1c91b2e3",
"2ca1e74707c8378c377e283428a048063042ca79",
"930f9b0a7e91f83a031120431db48e74c42cb96a",
"c5395f06741044f5375d8fe57e76ff56d406655b",
"9766c67671797149f05cab6e4d5a00ecfb744eb9",
"6ab3bfcba0577fabdcb84498441c6605391290f4",
"9a82aae993c8f927222833d5a8b47983af293720",
"ef4efe32009a6d9fa748a23287fa2a93b5475530",
"7484d737d5f3aad5f466a302cbb998446970e0a3",
"88a40297895d3c303a4df9e3e8ba5625ff96e9eb",
"f212dbb2eef289d961857480616af2b3af1d41ec",
"e8f2f88bf622ef1e4082eb060cf4cf176d5ac4d6",
"9b719d0cca52695dae23f7832e31c2597ac55207",
"43b0b2b426b244a4176fd545d8ac1a611455660c",
"153be9ede433ee2adae4a74ec6cf24cac5bbc54a",
"a3cce22f7a598f0d3556e47be3548261fba6ece4",
"72db6dd7dd3d0d9ff430e8c700a4cafaa09d873c",
"fddd0680fa219d76eb37b8e216419fb92be81963",
"2f3d1284ca5a2e8be35d5853ea40e7fb1cb9c4ec",
"6dd52c94fb1472e251110e439fe656aaed74019f",
"40f4383bbc94acbcadd06fce41e2960a6ffb9c33",
"28014031826b79e4d99abf6368483b8cb8a8104a",
"425e7b50928d5a9175f57d7455c9d4ecd7e253ae",
"104a1b96d01597fe30f292617f8de1e23fcf4cd1",
"227e13d5b1fca83ae6c84708e9ede117318c9fa1",
"2c6fa989cb0aebf6c8568851d2e409f80ca7ff6c",
"0d880e12e151979ab676083f779599b8f14b69fb",
"a54180199eaad468ee321c56a2f7bd44836b779e",
"5ffbf7545fa9c9aa2f9f988c78960f8b794d036d",
"d04d9d7d1fb0329b62673ee9ec25b1a2081316ee",
"c4d4ad7008b86a9cad4eaa7f442c7b73d283d313",
"854fc9af8ebad0a3323f34ba78e4b328e8027ddd",
"a9b94b0ad671e4d8e3129b1e2da86325a114896f",
"1708ddf77709ef8e9dc8cbe2ac8a09c0f9a69ee1",
"abf89438ea3e3b61dda68677761ba43772eac27d",
"afe13b9e47f35d8288762daf43eaea6934bf189b",
"9cd08a01db72752e4d844818ba9bc3e4f1912f9c",
"780f0eff37c48aff73f6e29dc327b8fa981d85f6",
"faafd21a91931211432eb0f01f86adea04496610",
"eece90e9f7d4ef37058c0a18b7a7e404f799c2c3",
"e5df616ead14ccfa6a75e8ca6b359de42d64d458",
"bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"55c4de0239b21c6eab12f85a7157992e1dabcfe2",
"b31fbde1593f0a24b5b9f75f89e3d1593934fc15",
"0b816d5c8662df961da19e1faabc126a9e7b536f",
"a9e3a53d2b13643769b20839004f986af21a3a8e",
"7126d051306fbb4c0e5a3621ade3e661aad0577d",
"a815640a3bdcdaf22d4753a6f73c53ed6631b3aa",
"97b1a5de538e6ea3401a1f96ce14d01742bb6a61",
"0c93a1c1a4bf141412700c55a7ab3615d4110446",
"5f1657484fcb4e05f76fe97c40ca5493c8a5d54b",
"a3ffe51ddf28e564dccf1558e2c3fdf4c62278f7",
"fe5757d12267e717dc7c6db65c51acfab70aa6e1",
"deeb39c55833948ded83193bef760850e69685d6",
"70d2e1a0db8defbb70aabc038189b59524c11d01",
"cd2884a609f3554168921451fa2fa9fdb07876ed",
"85b321f943f0102773248275f1fbbee3eb0fc599",
"c607619683e859fd715a23377c03fb08dc8090f4",
"2b771921d52cbe35638be461ee13e2c6ee15d8a6",
"0fcfbb3ecfa34f53d71437d27c791de333e9c42e",
"7fc3b73e8865af613f7bb4723107c381287b791c",
"1a0221f726225688928fd0a5644cb9ea336a8f2d",
"c07522365a673a3a6b15fb2a356c0b23cc249ec2",
"9fe5a8922f4936448daf35164f7189bcde812f6b",
"cdebbe5bb770dfcfd5c65c425b1a05c19abc0973",
"d77b5d5abe1032d48bd7aa0c1cb70272813674ac",
"65aeebb2d14e3959d9a920b919e9643aa5bbda99",
"7a1ba7d4b109c4bd45cac9c93755c6fa55823e3f",
"ae709b00edc91971136774e217dfc3957137dd50",
"95b5191533db1ffbd66e888b3503224db8f5d5e6",
"0b5fa51a9228af5085d32b02ff5bf5667dd2dc0f",
"4276a70eb1c719e2c7f26ac4db1f935f5c84c147",
"e5d8563cca462e832f8f14cc59ecd02504501ef2",
"f17df8822954871875468ddac13c3d3c9200eea8",
"574ac3566bd465d5306cd58d17ff9c87a5118ddd",
"35567583869c2c24a2e040a0f1e755d4e3d17880",
"8bf871903a79c3492ccdece14b8957eeecbe4650",
"53ecc88437534ebed1a23e213c1c84d39e673534",
"395d317954d604438a76092ef928a78101d39bae",
"e3ecf4d7a007f39742fc251eb2b6158727078f56",
"2eb665678e5310c325899f653701d79fabc8fd6d",
"e9b79fb6d0436511bf91746fdf40c22665348538",
"ef1ed621d78fe72b100b783026d3d6616d532107",
"e19c773a86acbdb931213d21b15249dec26454c3",
"976b58ba7a2622e134dd50704ecf7d5aa7a826e9",
"bd8e0ebcda8f6f06dc20641a71614e3778a43fea",
"ad7ba82e6adfc78510c7c49dee0ab908bd8556bb",
"6be77ca9c3f830aa28e03b532edd27590bf17c69",
"7834dccd2ccc988088c39d50169842c4939879a8",
"bc247dff2400ed4f454f1d76e6a95bd82f05b792",
"e55c86f1ce9e69cf3121ba7bead717f5faafe674",
"6ff4efebedd046a59b385d70f34d153bcd3acb57",
"f2fe0242e1387bfa0106c6509e0608c95e90803f",
"36808234a630ff2729977d1102fecd94f472537f",
"51e64cfa8b291d87cd055d46759be1d7f2c164b8",
"a5212a7a88f845550461b7691337a14ae9643e42",
"ea69168f44b1b5a1cfde6e84def408895f6c0b65",
"a71289f72009737b73505a1283443bcb03a18f3f",
"b16eb5c986dd71e3fb976832953349de13ece72e",
"d38846baaeeb0bcfb9b19d3a6819a0aa87367042",
"0a78b9cc5b25866a0df2231f9bea71fbfc0aa975",
"b495358c5f9d931514cc31952eebf94450a0d4f0",
"cd9b46fe5105c822223f68687d1a124951d6fb3b",
"7e13e0759fb66fd91d71be3b88c9c5688407ec9c",
"fd4f5fff7dcba2c67921c298b5624e75da7306f5",
"6744ffc3251df5771ecca9edc3e33a793874d57e",
"e90c6a49bcd3a75edafa06502f7d34277ea25f37",
"991505ec9dadc58f8d8a21f5b6818577c10b8ca5",
"2b9a014243b83c5955e529291c242727d363600d",
"9a60d4ad7fc6c7219e96a42b4f80007be6945c76",
"97af643a86c7abc4a4ed071f811a17a494eff48f",
"256c620d31fae417f95f9a3aca4539072c6e1971",
"345fa57b6429b31dedcf337c4b1ca21bd84ecdd5",
"081af03362b5bd3d637ee22011a4e5b51a1f1498",
"aaea06dd98508d58da1e743cd204829d09e18c19",
"f01aac88284fd7bb3d15b9b415f7b56eea5d6978",
"9cdf0aa1fdaff9f5a81b399ffbe8ac7a74b747c8",
"77076af23c9cbbf124755f3737d523a77a5bb534",
"24bf2826cc6eae9c5d6fcdc16dea41b07b8ad9e1",
"5b5a6842c1e36590cfc4e8182a91f7a92f132a59",
"e40e642e76c65e219eaf3f664ab7d01cdc2fbf8f",
"7b1847d8ad165599c177aa33a68b1fd98164def9",
"f7737b73c9e16ede8e08b8aee3668af6baa937ba",
"0bcec941ee29aaf88db7402491f0bfa53f6ae352",
"e695d06bbba0bcd32d9a76473e79b85f3caac766",
"dbf47fe4e9484afd16ad8521ae99a36a5b426bac",
"ada492f6996db72f256775332d4f669b9bc513bb",
"a4928f50b6d88495f13ff2d7db3157c920417345",
"474df7fc3cae93c7a098a3aea592587c6fc345a2",
"33be2a62da55fb7ae9a58611ceee15f31c214abd",
"25c7162760d421e4d85a1c7d2b3b51e757b8771b",
"98b0d55fde56a946ce4d932cb116958ed0e333ae",
"3535170f2d2683dd3673f1f64536e96356d5357b",
"ff79d15bb86d9030ade6e3fd7f403a904ddf4bd8",
"e6728db15acb86dacf348a16aae9895faf3de4e1",
"8f89f088c6fcc5722dbc19488c9908454d917bc8",
"38a76a42deed6cb98a4c8ccf7874b4adca3e6b07",
"9f4227d37861621eca6fd102f64bd7c3f33de117",
"0581c017ae1fa7cd3d553c855c439d40e12357e9",
"ea31040ec6202d748d4465998213f91b213cdf71",
"ca9d2b44dfa7e62a0c6b08717200ab909de74df5",
"6288dd0a244e785e87b81cb1a465b7c30ea31421",
"057af40ea360b4372bab65c4a60a8555afc58cf5",
"8b1dc8f168be7bed29b8a8b2477ee53ec358b2c3",
"3aca2a11b0178854fe8788eb42b4c2265a0423a1",
"04a4aa06c919b3666e48623768e5580228bbb898",
"f1f1313b6da0a28bddd93a1c1e0b48e9fe43dc30",
"d771ce85224c9abd4fb731f1667259751537ac34",
"2bcb03b021af544142532e97441d2c9efcf4a688",
"0e880e12e693e4868ade7279bf71c83e6bc12ed4",
"f15afa84be7bda050bfb93e321bbce28b56d10b6",
"ddd4bde302b7ff017a60ad4c4919b2382537f161",
"6569449fff99b251b2cea96cb76eaa0ea430c63e",
"5fce714ba55892702069e6df36666baf14c751a3",
"5ae617abf096d31181496e6b5b048e81872c462f",
"623ef278d001a33d10b3c3d280edd7312002e663",
"9cd1b0ec46c73e42e9c4198909f19a2a748a614f",
"cf8f262cb23282de93d8515af0cef6d49d99f419",
"74abd789c7c156f5a6e3f9abdde0682504db5425",
"62fa8c25c87dd5aa56993a257eb067e4cda16d7a",
"15efae2a7427f2c152e273c2fc7ee8f3a7b30758",
"752656fbfa6679d5c2c5fbc6744bb57c958d29fe",
"54aacc96197a48b79fcc260f94312d824f5e0a34",
"d7c88f12ab444d2a3c5e807b6036b0d91652f095",
"de0b9ae44df7695f74c4012203f1d01d7f258b3a",
"eb1ae13e68d8675e30d85fcb86666c78018e4bac",
"f0b8446515f043156589ac9db8f3a635938efe5f",
"3ad2b4431f4406fbb96c30d1edc77c5d969f17cb",
"0f0f9ff9b4cce526ac39a4140a6400b1bd7c6368",
"93ff59ae250a3f7532cd07114779072f8aecf260",
"fa4b929a06969578015ae2a8ed1124f64f7714a4",
"570a7eb141b6ba001713c46345d79b6fead1ca15",
"14ce5fe7b177d57ab33872d90c5a819c5db13bb6",
"ce1e1f71ae7554711f4481faed9b66543434d3f7",
"18fc41c53f181673189dcca0213aafc38229c0f9",
"864ca656c09d772cd465b518f7a857b8282e55f0",
"71d4cb012880b091779a6d39ee073d8d7ea3eff3",
"2fe0cca6d97700c4ef78c9f04b8ae52865ca9910",
"98bb91680d27a65455a87b6ba1a59c3d7717fc4c",
"955c942c189a3cc529a070919631bc0951295398",
"088549a333a8968a2659b867760c6f62f7387814",
"bdd1b238fc70db081f42df4338f91363634d5a5e",
"3d7ae89a837dadd5d655aa53d7bf0c19204d2b8a",
"7ddb1119a58c37a711e08968dbeaac27052f20bc",
"325289d28f52d094308902fb0b4671cc30c6572e",
"b1435629f9b2e5d592971350d15162cc1e9b427d",
"c02ff1e47ef67929ab7f6526ba454e5547d3f180",
"6efd0d97a5d13a37a7b89160b84f744f8a4f2ac8",
"4b268adf49ea63e716467c4ae9b01e52ff07aabd",
"68339d86b964944375f13b154f5c7428702e0f72",
"4d50f79f1c9de480af225f7d1b020b5235ee6466",
"87d1cb50a0cb59cc0428425d1afb0ccfd889b36e",
"9950182ee02a5b4db52fe87e0b846c4abe327425",
"b917c1b41197a2b92884f92edbed417902a9ea59",
"d1e2e3b61e203ec223f5955b7f1b8d6f54be350d",
"acf71fceaa0143d1ec666be68a5a08b42815536f",
"428fa0b0f24abbadfa645999319b85f9fa160ab3",
"cac6c0aad74a0ea107002c01d302967feacdf6e0",
"bb4ed84b951608ee62123be1440c73fe9c646c26",
"13d5b4f62043b65aa4b7f31e4cb328c5c826afdc",
"50833d88d9ce10f1f056598148a010e28d03278f",
"b6e1385e39e3d454fbe16088207f5a027742a11b",
"ccec3f80dc8557ad30bef100a73a395defd88b15",
"3bba7d16340a546b9ba34739bdea96ae4b4bf041",
"73c120d8d4ab10c2e4b7c2a7318f6d7acecc7bc0",
"96c65eb2b39d8adcb80ecc9a0cd3241fca394221",
"3a2e06e498dd28cd3bf5893e234490e12e739cfb",
"00102beb298296b793e164f2455fa7d4cd4b70d2",
"4b1ca18d0ca0f951d926a5c048f0365d740420f1",
"fb13e5f970f7712fe904351ea2812253000d73c6",
"e52ce483a18d255e911f3f19a8fb9011df8ae91d",
"1c4a2cd1673e91f6a0fc0ee96650446995552b26",
"786ce40f9563d9ee8d8946708ed39f9b5a70b87f",
"5bdc2ad1fba5346005e6e97ae0161d602d890163",
"64fd41961e038d171179063174fda182a89099dc",
"e1affc2da62417af41111b4af714cdeff49bc185",
"501b6ba9eb9871ca303c631d166c92c6ca2f1725",
"a48081f2717f069d456ec09f31d9e639b232dbed",
"091f7b7e986d05381718e2aeed2497c55dd0179a",
"9c96b46c592aafc0858c4d4babafdba1ed59b88c",
"9c9bbbe7bb54aefd844a4815c04aea3e34e4ab02",
"d86d99e0021258c701deeb293ab3b192ceb1d9aa",
"b0fbbeed6b42b1846dbd9b2a2d45bc9c2b25e881",
"d16ae3edc9c96f2d2241dfe92dcf77f8d60beaf3",
"09f2befa58dc6057e052904b6947bdd17d3b0553",
"0726754b0e112802dd1c942cebd7850d331ce483",
"449790e252869a9ea22ad139cc364424deeda1fb",
"9e745b68d12d96a29d9aab3320438a1b231bdd17",
"985b0af3f6230a0d36e0b413f42dc9a3c1522fe6",
"b26842d4d80c45f969fd244a4a740109316945ed",
"f7ef9cc8b35a4a7f9de9004d3bda0e54ab8db707",
"8239a1d0ace922812c6121039f159c98341749b3",
"a1b41542b8274d9d17d4da03b111d3b4a80f1576",
"25ff5876ec43d2b1105a91a58a71c5dcbc89e136",
"8728d02c70202594858fc5e9fec308c107917203",
"17744a03fd9e2bd76304fe52602ea9524d927006",
"c63aaaceac5cc3b077b53bb517536e26e567a930",
"eff40166c9ac8ad9776ecb6160d245220bfb1f87",
"6b4f055c36b5493242d019058e62657fb4abf10f",
"0d18a8fd9e37ca9d5e9dc01566ce4debd16b2a0d",
"e06dd208f4b5728c25ebe1b97b9fe7d034d4be7a",
"0908c65f504ec56bcb368b3a020ddee5f251eb56",
"9767b485c2aad1e23097d2b5165287ba84cfa452",
"b477864b83b2c33f211c827ead7026b129031dbd",
"9576a6496b5a2557c2f7522e42ae5a38c3aa4d31",
"4307bdaae4355213efdaa46afc16fed4f53cb754",
"d1f4161ee9d8c55b7e9f7c42b28a9b3277470032",
"286c639e262c4d1aefe6c40af92c32518f807d28",
"d6d90c6fdcd052dcbe44a856acab59f24d482fd1",
"664cf20c92548d7f2fff6191c783c0b2938e6d5b",
"292ff01923de86b9139eae538962e98d76178b9a",
"137961c1f72a6850325b05e65a232cd202cbd12c",
"e5fcbba4c04369e1124859ed845f711489910342",
"d37c52aadead4173a67e81b1e73b64cfbb275145",
"565e3b889cea6bbc16825d801f19a1c87d007ff3",
"f46d396e12e880825cfbd10db471db4f4cae5b34",
"d901b911c6477f30bb00324af12eea0244f5cdd9",
"113060833142faff75c3c5add3357a3cbd256e0c",
"fe55de181d4320a0cd7a6ebd2820764280ae9adc",
"98c94de5e3db8acb55433ffd95f137396cde6fe4",
"bb06663d1c9388479c1638624e293a19fceaba22",
"8928c5ee2628e0b4d738289b5030fc3e2a918e5e",
"5abd7bf55a093341231c8b71953777068eade0e2",
"e12bff0871a57116f057fd1a93f7ddede8c574bc",
"e799a7ccba4cbf12736362a6e7d47330a845fbd1",
"29cb5c085d026b9595f935a6498b6f802cd97910",
"db6cb55d6c66f50773b9cc1ab4a4afcfa8fd43b5",
"0a3da17fadadda149035fcf1e715dc575f340ce8",
"71bba29c9a164e23c102dda5cc19834e79fa840a",
"1ece339eac894321620a3b6e5d97c16a3add19c6",
"4e9e438f4182c108eda607fdcbe890166c1301eb",
"15d17098315469bb180157d1c20344faa10f4f73",
"f38d2b2ef81b254edb6f0a58429ddb1a63c0e418",
"159944f7b573753c3a552d1fc2200f195512be63",
"b5b9a553060d6581c12bc368645a8f3f8ed6a23e",
"921f9f2d761a3f88883b60894ce623f5efaaaaae",
"1af505c5c3d5b3924fd1867503bc6d743642b022",
"5333f8217aa535b89b834d342fdb54a841fe27eb",
"3560e0066d5c40ee9e36b5b1aa350815a0826830",
"8858cefc89b52ce5072f6e859961a4ff3cd5344a",
"e58419a9b0cc21a7353c7a94756bb6bf42326ba4",
"3ff1ddd5e3cb3469a6d7bd722b0017ff2270fb42",
"d7ca9ad3c0e77ac32f0f2c66216cda99761eb332",
"b994c4a6efbe237dd1a939f5f97211063a5f18ed",
"c13c658f4e099e74b551abe6b23d0de8d7e55e91",
"131103cb53032a258badd7a191be4640a113a3b1",
"7a5e5ec86524afbd372ed14b7f8c9c16b64bb4d7",
"aa9c6542ab591a16870e05586146fc72b2c27708",
"49584f4e732fb0039d2089f3c39fd56fc34a2ee3",
"d722638905888f7d50502e6ac37aa2011b659a26",
"47799cbab2eca047b6520b9fce805da42b49ecab",
"ae981ded6ed2ed2cdba34c8603714782667f18a3",
"a60afc8350b1ae538cf87450fab20b1813e5af2f",
"92d6fd4c7e85ebb2a045068fb8b61edc1f7ba099",
"eee304e0b70ad98403d8779fa4b7103c0f06e6a7",
"a46bcb224708402e9a3042a126a8154f965dc71e",
"7feb3e3b10e362331b9347b408cf4eaec73490f5",
"f87dfba9cd9a91f4fd7a8eaa4d7847ec58f02fb9",
"7208d89c31964abaee4faa6ec53f6602e0f1d534",
"dc8561847d734e558738974be13015b1981aa1cb",
"7b3d380ceb5e268b28c2ada97dde0652d7ecb35b",
"0fbfbc5721b09eb2b998640004cdcfae7b7e5486",
"5dbd9bb2a32dca6aafbd2b4a50dd73d237ca025d",
"f03c734e85c51e1b5baf51dfe6006eacef261527",
"c4afd897f96448fd41109618a786edd11ad25add",
"ebdaf0edd9734cab5015aa70a0496429d6a5affd",
"640d302345a4dfa196320432e1b674c0b7d946e0",
"f4f479d68fa5dbac68569931f3e0be580c6be58f",
"44fc11dff88fe8dfc2e323d989e26d6cbd19f961",
"ccc675b304139b783975b1c78c260c6ccc5c840c",
"55d16ff2ae8e4fbacf4fb0cfe1afed00512bde78",
"045b3e717500d20d51e2932f5c654638736c8138",
"76302ffec0ec4ba45f1754da1ab681a5e5a962c8",
"ed006261d801d285c91bb33315cf4802de1761dc",
"d139762f4dbbb4ac72e72535bafaaa05e8284125",
"cf3cfb7efde507f264cc1c6a8010fb90cfb65ecc",
"119d48bbbca6c5b1001b85cf1c986934a6721009",
"f7b53139f48cbee3a0799b82043b1aec675fbb58",
"b6d8bc94897cd547bf564f574349d22659ad28f6",
"16478e721bd506b6c49a8ec69f5d55036c3f29f3",
"54c2767a1d0c04a60687e262098821c93c580f42",
"1e2776cb0801129b8f1de375b76dac446ead9f17",
"fd38d88e14027698497dc724b529d4a69f5abdca",
"25ca4c8b92d49763049fdc9c4ad7a1f02f8b8f21",
"2e781b1efdbca8781c43b43e350cf17fce8d6750",
"498da296fd6f2cb89419e4aecfec845ec79032b1",
"c8afda2ddf00090e1e10e44a819aef68f408d126",
"073c55fa3b4657bd2d60ea7fbf0d30cb8f9b0aea",
"14b90ffbf91595c347376bf2f7f6a772aa19fdb5",
"9b985426924bcc60b3ae88916bf2639c0056a9a1",
"8e0e1c232d14459ec19ada8cd937624880877710",
"93a6f90d6e7a973228895beecd1d0a2fab0ff2a6",
"7d4ce8207d6616f9c6cc488503491cf08e2ff054",
"b57099a0d000a5249495fb5c93b50a5649a78c84",
"a8cca57c0af3c9ba90cd8eee840eda1519a2e524",
"3323082ce3390f59d6101e0fb44f29ff4249be55",
"6349c1c55957083ea40570d4cfe667eac3e86a8a",
"9f9df6264ea48cedd4588e09e0fa103a2595c5cc",
"e4f06e9c9dea7b60bd8d565a4173873c0fa0d1c4",
"3a3820b06d7d49f01a0cabea44eec105524e3405",
"7169e97bd59424120ca8aa58d62e1d8f8965bf3b",
"6bc7d297a5e7e3feecec3f61327a9adbdf532f61",
"59c101fc592101c81120d0be68ba26521cb51243",
"50460842f48b461a53529814078e20efc9dfda32",
"2d710936087a0a41fc5f31bf2ab2c3dbe0a6e77f",
"e7110efbf639b89878b55e3b325bce4586fe3718",
"91684cc9ca43362db0e546674d53a6322dda039e",
"04bfbca15d5fd6b8ae5d540a8c3166af463db653",
"150130e99beb04cd5d989932a617fcd160c7345a",
"3cf51043b3c4f253334f175d7d14f8183ca7e05e",
"e3b3f3c4f4fd1f8438f37dc1742a7ad9a4c4652a",
"f6e2de30ca40402aedc8c062ef0bf59e05f51919",
"6baefdb13fa58f4f299b40d915bc27394f20e434",
"79c1fb309e0a0e3cc350f4b548e7950e34663d8d",
"1bb400c278f33402cf28bf3c09f849df69589a0a",
"ee3dcfacf0a5bcde385afa81f4dd1c086183535f",
"5331cf3bcf2dd75f33d75173116137c3091aaf05",
"a3a8060e5c0eb2dde413dfa434e70b5f510c44b1",
"2dea54c6eeb7bf3a177fac77ae04fd4aeadd772d",
"1f36879aa20bc1aa68f9a1d2321d573f6e61fd2b",
"48843434c701cae9a7dbdbf0e08e3c42b5dee2cc",
"2020e8531e34a0b67a78d8b5a961bfdef462a55f",
"c94df2d5cd5f65d785c1eeb4acbc0e1352e083da",
"47a440a384c8a32a2de65bba7dfec3739ab5ed08",
"f9d9bdf8cd07861187cc335a1f5f57ff64316c79",
"9cf6fab7c8bd043a2fcd7d10eeb7ebf7bdb5e2fc",
"8eac221f4c07752530498fb4410af068a9c07b43",
"a6ba1b010320d20677fd5ccc14c2a4f7cd6b0ca4",
"48aa725beafa327277f0772347f63c4d1cb6b6b3",
"f90421a6bb307b720a308b91338ac736d3286ca6",
"13db55014ba33feed75fbe0269d24047addbfa06",
"6eb2772235b997f8a506784dee6f45a846e43c41",
"67c950954d4ea7c85ce9ac21d1aeeb6ea3a028c7",
"5e3990d411f6ceef2a058ee30b6eaca7df9b445c",
"59f506dbb5591d3fe68e638038495730c455d72a",
"48dedc6e7e79b7665db6c7b54157739366f2d616",
"6f7c2dca91a0c721ef44562ef70b130c58a905fe",
"bdcaa6047441d6a7652a1929b27909c16eb86ba6",
"d9a84de5eeea8b2e49ddb7178f0e82ff877ad558",
"f4dc224b3a63a19d3ab6da84ff7f54a403d4b87c",
"4afe235a3c4d94997e6155626ae16770cb7fd168",
"76c969c7557c7b99e2a4e79b058856118ff30a05",
"070e912b3ed9b5bef35ff6c9cdb723c1daa2fb04",
"c761d03a5aafebc15c0f821f353c9df06b509281",
"99aeae19ea105660746db99814bc1f8ceb7133bd",
"9ada30255b11e331a04d11a36d0088c66415b0a8",
"63469fd3bc45b7205ddc80e796e47da0d3d07ad5",
"e894b6512df2ed567cb540a304ce85614c773953",
"53c08f5d26f4ba71e60dba5fe74dce620fcaa841",
"cc380532c63eefa321c578ba4495844b78f1366f",
"87debf380e5b13f2d633e9e8c79929152b575d79",
"ebee41fbf12255b2b9699c9fb68bebf90553e9f0",
"376c3caca0fd46cf260a6ad6e336e197f6994d6f",
"9f544ef8c185ff5e45619b2333dd63c445636e0f",
"44206cb6caab5b2fd1a49e7c2217a27924e82608",
"d773659d66fe64e639904d9c47e8af347b6edc5e",
"ecb59d687b216a3661f455f63e753e43842e3bda",
"57e3b2a154a234b5c5049290c7748b52e58f63ee",
"0e8a64d0f867abde7e00d72a3b5a21e92aafb65f",
"74a0d7a4d230c0f51d64505609fd605197fa792c",
"bfdf82a69a2ea5cb00e3edf43663f886a0dc9fd9",
"472a1e65455131c942171b8706efc1add981ccfa",
"5af8f706655c4e8c18fcf80e3c0818b6c9305247",
"8196027f3528e344df19253c3fb643b02d51440e",
"9aee9b243656852b0cd3ada28e39899899a0ff0b",
"6ca7da276839e5217b340dbfff8cd9095d8464c5",
"1b026ae0ee3cdc7865ea874a14faab809594c0c1",
"e65595c4c7a98307be5ea8cd977b221c7a39dd53",
"f453090e27a6be99aaefee4e5eac6cdd4cd7ff7f",
"4605348d68d5ebc27cf578cbec759b56b0fc1ba7",
"ee9ee691306a8accc627a00835a3116e9d235814",
"6a3a66ae9c5d916af014413e79a0df7279c8ef1c",
"3681c0e6dfa9d384481529813be35a867251d473",
"67cbf15e4566cbf41214ecc919f5694e180cd542",
"d32a10b4b932e979d9eb1c4a8d1515ecc9db3c15",
"dce5316cbbd1ffb17266e32dcb9b56aed5a8285a",
"3e07808ee53edd9d64ef6c36ecb05a716fa9f374",
"f8005c74c6a715efbef22a1e72a50f680eec112d",
"924a2624a43e1497b48bee25cc8f12cb6bd6e102",
"0decad55867247c3f90ad3419cceb8a9d1ca5e2a",
"fe396ed5f48bdf2837f0011df92c20101fd15600",
"1af9480b088c3eec800040a1bdcd09941a31bcf3",
"511165bfc5817cc1d81e6b017ad47409125d2d3f",
"9341d51d0522fd586505a835d00fa47d7fe7111d",
"af095d53ca79d7cc6355d147e8c3990d53c8fde0",
"6b04eff34ce4a77aa577703b0e6fa1efa9a62a19",
"df785aa0bf347bf463ecaa6260b8fd393009c4ef",
"72b00e3d41aff7a09679356b0751360b621a2388",
"9ae7fd702e5901ebbcd6ee346e28d1ace539dda0",
"0af233cceb28c8049d6909c974f8145644347750",
"bb5fb5e9d9de66731cb1d717a51005fc8c64c9f5",
"538ca1e44d47d2183f3aacd92d3d12bc0c1f108e",
"5b1cdbaa4ada3565a019eb743785b2fa916e31da",
"5f96429005cd07a7ba4ab826b5e02b30eed3ad94",
"ad7a3addb695b7e72d20e75cfbece02f5bcc4114",
"59a08f21a44538d824cb866e5dfe50f29206c0d0",
"3ad97fde0b88869d744569a38291521ddb5b1cf0",
"638c2a3e4c9755a98aa24f2c3c2ca6277e9c693a",
"1cbca28b7c35d1c5d067f139753087f6188a6837",
"8277559ee0bc821cab3a2fead7cefdb61f7cb5d6",
"0fb1128bd319155d400f463eb45aaffd7fa07d1a",
"d23120ca8bf082e7dc7171a3b53829593cbf7701",
"53013f306fd98469f9f1eb3e830361fbf3b9a7d8",
"2917198d1cfd7ccfeb9d6d5384b2adb7bcf6f51a",
"7d67dd6cb6c5014aeca951a5e89691c09c7283a4",
"8e76ce03d5025ee0634d9da104769c55459b72d0",
"7acd025d7f6570b114f52a86019468490bf6a0e1",
"725660ed515fbd8d6d00b93ebe58879e8f4bd9ef",
"6d791ee143c86ba1a3dca870089732f47a793740",
"dfe0cb43429e3364872da505ccbe829be93a05cf",
"b64fc22c185291a5fc2d7396b88207bd62e89244",
"e703bad294cc89358da319ac5f94cb89f22b897a",
"2fc65def46564de46e9b1f5b2b7a81e4029b6058",
"3ccb6a5fac2b7dc9d7991c5b8c5767a472c7e1f4",
"aca5cf669f537522dcd7178e6dbaa62e49be796b",
"6510705521d3bf8d30929ee5f69f3b2a5fff8a9a",
"81dc849bce4ea10387c8c499fc94398608cf0cf7",
"30ad7e4d67a079bd129d8cbf75504f6118d56947",
"358324883c0aed8acc40e7b565663f89b236692d",
"b140d8580fb00e22e08fb5b9a755fcf13fe3cf74",
"d4ec2176bbbec9eac876af5bd06c46e651c64b14",
"79644941bdfd595456e3b66a7d6630fcac9c7699",
"d3b0483f426f60a36f0c2bd0f8745953429e15d6",
"ca557909c2bebe2b72bbe9734fe38d49129b5e13",
"aa13f57e7dd96887d6f53f278f2d110076951b69",
"bf64fde8a143e0a419f7efbed72389e3dbe89f04",
"5cb4ad4622a401fd686cd1c801175686ec4a5805",
"85d452b2221e125923ea87d3041dff46384d681b",
"63ffdcd46785a5e426dcccb9c26e9f6cba84527e",
"ac849f1fd5ec61051d77bd21b371f082fa4f48c6",
"40303cd8e158cf3620c370c566c26c4cf2792852",
"06946a2bf4358a91129392d9b385297e3fe81fe1",
"cdcc7cfaf96b83f6d771d02d5971ec1949934d1a",
"4da63e97d16e0261ce41d5487b46197f9a321417",
"20a521179cb9ac8eedc31082196d534b1184ba16",
"39f65e1b29059de75e0e789cd9e34109049c938e",
"bea86871de949712d12ae14d993a76e56403ad14",
"e71f07e592823faf289a3c13c4b6143d13146de3",
"25ed6b8b28d2280429b0de7d8dba1d0214891b63",
"fbc5c5a0275fb28a5ceaf7fd19482d43bb2226d5",
"fdf693c49797c6e6f72a27ef11d12c041009a3ca",
"2d7193f4bc7ab12133dbe8d07efb91626e3eba4a",
"ea4104dbd7315f6bd22a28454bb2e946b9f76759",
"0ae3c00cd718bd087a7d714a688e6588edb8bbdf",
"3cad39a3a95c73c84b4e00dfdeb7b9220143eb39",
"269d21deca0f97d9468205074d4ee2ed17148818",
"9f45405c648d246227d2653be4e22243b979094c",
"3aad82d158590835d0737bfdd7125ca0b040a929",
"2903b4f09a9404b1dc71402b0446286a684b31ca",
"b6751855388454acf691f47e705f5032fa6ab15f",
"d88cce484a4a0dd557a625b7fdbda216d13993d1",
"cf08a3f7315143a98dd2f6aa75e09c1035554f22",
"dd16356e4e1a53d26dcaa1c07da44faa080cac0d",
"d27cd0db0c4d5ae4c2f21ab9c4354e532268ed64",
"61b06553b461b982fb59808d1dad9d6a1548732a",
"92f21d7f299c71a8cd7848cbec92df34fb92fe56",
"559f84d9f1739ac7d7a98a1e7431d431639648b7",
"0640ea59ec5e4cd96b26ac2757f817efdcc26e1d",
"c22bf8475accca59b80ef4c1a08a9d763f3da686",
"82a53e3a53671fa1fdc09b474d9a91e61e83b963",
"9f81de7ef3dff7ea716056e11deaf48b1ddea0be",
"703a6d80250d7cac6584811fc4553746b4e46bd7",
"9b7c48ab401cd4310f8cdc8bea4ed6b4235cccd2",
"947f1bfc018a641aded13e7c0b4ab526cbd9b117",
"f0754330c9e7e89b278a21626288e9f428b879d5",
"f9df360171b64ffa7e3cbe96a3145330dabc3d86",
"823a7e7c52a21d4450a1326df8a5ed315163c811",
"193ed2f675ac6b0d1ab79ed65057c8a56a4fab85",
"65118e6ce9447c14154ec7154e7a1ba997bd7776",
"d7abc0a8fca06d2116955ecb7de2434645f14098",
"ea7f26dbdf78c0827074f3567aa7bf298ad550bb",
"981172aa4f3e84c076a994c887735dc392832e1d",
"87187d47e5dbc0da7f574a0b8b36386cefaada5c",
"f1f32d8574583e70f4d3f397af7685f3fd44984e",
"adf31304315b54446808bd5ec4be1a6b42857edc",
"75b52e28b2445472d283daed405c141e77c85883",
"b503aa6be4e9773cd19d2fd8b2909467507b5c97",
"dfdf2e20ccef961376d77f0563d04764332b2ad8",
"ef6ae0fa84b912c2cbfffae93d0b24269be3a860",
"c06b2258779b78a2317084b8da541cfd0a64d6f0",
"030419932e79fcf64a3b5a9259725b433932ca93",
"d150938b3823e58f0811fe03bd25bf590ca77deb",
"a70664368e76b5c7d4cd285f3dbc4d9b0193d2fa",
"d15534df971e9eaca1a2fa0cea151fce67b48ebf",
"84a95848b02de5599f5a2dc905fa2ba4c185b7ab",
"135725d6f6211f47feb26cf9a276ae2a13e7101b",
"342b05f88d0ab9e81b03db9427b1d641cc5cb749",
"d8f8d296057828b90ade8b875e121a0831f7dc43",
"0b6ede69e7ae15ff9a30b968d6e5a70c3b9a6256",
"d67f9ea9bbce819072d430209343b1387d136805",
"15cf5c610060ee0f6cd007aa9066c1cbf580d24e",
"1811c7b8bb6fed15cd9adf111474f59efbd7e517",
"d9be25a477a0cc75862e17348ded54ad7a4c6d4b",
"c82344496bb53a3c1151d3bea617e7bbaa4c920e",
"7e3c7a7ae08e7fde67c26596a6771a0a9d7786f3",
"90f3a37a08fdfa2b9fca59f285be898fb6306ac6",
"199fa07a79cbf189ff7e901c331f524f909affb5",
"2584ecdb0a3891eeb8e89080507d44cb49c81327",
"1d167581f2fa2e8ef0e36a268db1affef7418c64",
"c99d9a6aed7546d54534ccb53f198dd5672b63a9",
"bb3c1b56845cdde95bfbd61e18e8f514efed1f3d",
"8657cd8fc8b13bbf2b2a3b73ab653504cf00f800",
"5709f5d886ced23a152b751d5dc819e2b09b11b3",
"69fe1d5989b45a43fc697d0c86785bfb9f32d570",
"c3e11057ad933aeef27ffe091be2048557cad469",
"b1337854498b6989cb24e09b45013a8f0eef2596",
"504a198cecab3217b46d0dd13ae8e969f1b0a19f",
"9a1a216f70e9ba580c1ac0311383614f09eb9bb2",
"78e68336726e390dd549302e321e8d301118ad97",
"7c842bcc1d392184846cb67082850794f4fb0602",
"499738de711ee96343163550f2e053bdba248c1a",
"cd4c44986aaaa537232d83efe4020c2349efa65b",
"2011f2b06e7207498aa084a25583c3c96c782c2d",
"8479666731847f3888e311e23aa1912fb21f9144",
"35da28d8af08baece5a2f0d5baaa4fc3dc21ba6a",
"313fc1315d04fafc99ba0cc5e23fd40ae79b2449",
"154566f8ef3e6cfca6265f2e645e507c5f0abefc",
"b896a7fbeb0efca0b97de02b921cd51d3c2ad3d0",
"bb40347121ee3c231aab84be286495a810326457",
"6a5753f4bc9845b5482256b6904bb43554ac10ea",
"dc7e126c85543f9e5d90854b9607c608c93eb895",
"5442e6699d322ecb1b35d9448b0d305f71333276",
"90fe50c152853e569e6af288041f909694ed7902",
"7abfd4870cf22731fc3999b3c4d8091cb9ba1c53",
"b482ae85f0233e6a597bb98d17bf222612c32920",
"7e32f91ea29a79ea8571809dd494459640a0b052",
"c0271c303f5a88ac6b2274d34614850b3afdfa41",
"a5a553815cbbe95b37780a0db0b15bedabccc29d",
"5c326cf24246ca85d9784b1f620c1abbb1e5ce08",
"883b548c61e1282499503be2516f5fa6a34ba754",
"5acfffb352a47e052673f7ecc0c87653bc6c8ec4",
"e57dbc337a5751f5a7f2e2579cfcbacf0725e895",
"1376ab63c04dc907fe44d58c9046458465a08a58",
"c94bd50666e18a207b1bb8f3fa79b9b0b12e8207",
"8e58ba64336ed456ab577ab456de0cb8ebb2a96d",
"cb78f144be29ddc9f65a6951b25b9c91f4fc771c",
"b337e1b1cb7fec148d26fae84958dec51743616b",
"5078396028e2ec5660aa54a00208f6e11df84aa9",
"fe5d473af7065d6aed1c7761c7c68c71e378456b",
"8cae60371cf36fcb42f5c207a03f2c8a26000051",
"2c4e93b3d213cbbe257ce96c8830432cbe206cf1",
"9df1922f15ca5a27057ce0a8f7197efe3ff32ee3",
"a3f460e67d90f3406ec2dfbd1f21c3876a38c65a",
"1abce45d5d6e565ab587513d59ce1c16c061f80f",
"a7cd7b25f56ccef812b40f64d31e2565adfc1f4f",
"af724eeb0dde8836bbc610424cf661d41746fa98",
"6bb0dd1a28ded30b80f3c08d1b6c9ba0e1e2fcc4",
"457b82f72325f554919b94d808628014e484494f",
"65fa3cbb1bd3ddaa56ee8e19df8379345d366d96",
"66950744794ae7dd4d0840c3bc38e1624143abcc",
"c903a958e7600f4758997d82a0e2d5017a82df57",
"f760b1153feb8b9e96493f5ac8dc1efdd7ba580d",
"5c256c8bfba6e205e687bdd9a0289679f436da3e",
"5fc6d960766c89051b360992a6668f7ddfe1cc3f",
"bf8cee2446a7c9933d8459ff75b703dcf52f3f38",
"287a920d1277d8f59a77bb324c2b6977e89b76f2",
"579ddfe72535fb65ac4c5cdddf66d30c683badf6",
"5040f33025d6ba7a68dca5f9e1eb8053888b623b",
"30f2e2260a93cd2249320986a68c94862099da53",
"5466232dd43b4da224663bb6d4f67d732f9460ec",
"54cc92cc83e5de599961cf940d06e546701d879e",
"152be650539a7d3fbe3c0eff3d87d88fee94a9d4",
"16d49c0b821746bb6034d6d78c8ba1ea01b3a114",
"1ab1da1ba196ec3fd7ed6b15198f4b4093bb4e6c",
"112c940d8168cbcf1fef3b3f32c03296aa32e179",
"45a2c05a9e3881353d9d9d2e7fc6aba58206b09d",
"1acbe393404e4f81f5a18e9c0b264e79c529c2f0",
"9de10ade5ab506585c67ccbad42d10264cc22f09",
"8199f1a679421a3405ace137c3796395c1a903f0",
"56d6e24ae6676941dee0fb09a653d0d1b2b02e29",
"ba5ed58997a6726cfb8d8c9b260f76c3dd131073",
"befc76e0304f1891ce5fe7921acf2c486d5a5054",
"f2e74fdad2f1cfe0d85c642e40ed3a43710f06d6",
"d6d280d450419f4eed7fdfe634ac6e47b9834ca1",
"8ea99217656ed6d52edad9ea94452c4b66b4bd0c",
"4fb5f6c1725bf9c11d71a00a7f8b1b0e1040adde",
"27e2f472802a7744af68f0b0df35bb7dd4b684ea",
"3f592e23d44cbc06451600591f37e65d6d0e57d9",
"8d5299fe85c8a88d0604b4b21885585a0b567187",
"b1213931de839587901ca482ece2e3aa2d0ae606",
"46b0dfb11c197053e5557ed19dbe06044951bad9",
"a84555955d800c0859f242b31d37b354722fa57a",
"0123433f8162ca4071eacaf14954af64a9abbb33",
"bfc3c7164f2e77e797249357910f3f6311442a3b",
"6c5cba3ca600d0577f3d99ea127225071459ba98",
"aec865a986393ba64faf437ad1c9d523ff45f3bb",
"a46057da1f166eee90411ee27580efd4691e9492",
"e59e196da8b8fe5df1fdcf3187e30ccf2990db3c",
"0c43b050668aeb7623d75804b28d557ae2aa247e",
"df0b5da5590d9835375fec0a55db0f1310dd1cc2",
"6fcdb95f0a8a151ecf3272c7e8d05bea0c03e211",
"04d70f27d854803b3f49c9715749e5338370cfef",
"9cf20ddef918ee945e978f5311a9a69e94a7fceb",
"09a284f09cdf2700d6817b8cebc7e11187d2018b",
"a1df6d37488c01b6db5a791a87d6f15279068c3e",
"87c38118d19ce3891ff7c0d50107e28a81e04b97",
"9a54c8da7bb9394fc42a8fe99eeef2916b4a0fce",
"257b950d6f45b8f99db8c0463aec339899441d20",
"27f39514d4f79fb384ea46f69d75e5ad806e7f54",
"47f09e6ff4b91d706a222eb9a7cc562bc4dbdaeb",
"d8b5c1ad1c9226e5a720158e82b6cea847aa3c79",
"805bd696dc20d99e3035bf1c11d7d138efb5b351",
"6143c37d3b86830c16ea284fa15788ed21c9cfbb",
"205c15caa692813510f2b0d5f09d6956c75b7eab",
"f6bd7a3dc6176adbd8b55f3a0801b6ecb26b1649",
"994f52d6541f7bd3e082746e39801d01da030b14",
"8cb8398be99c3054dcb5b1a2bb59dd00b65baff9",
"534503d002c45f8d5a74a995e64a76f49d3f363c",
"f282e09dce21afc1655496bdf25b08a5f568697e",
"2536efcb55756d227220bb63dde0a8d7b1e01ca0",
"a922ecf3ceb4eb4fc22236b0895b18548b50ceb4",
"95a314688589b8b974015fef57f1e0b0751692ad",
"0358d7bcf084518261957d7c53774804e92f759e",
"87870b521aa8c1af94e632963c8ad2810fb3d4df",
"9bc636ae6ede6d03a33ff18480b119b5339e9bb7",
"38f326948f9214c18f2a76506aca432b5a1c10d9",
"9f5ada5fa9e686a76a1856136ebb90359ff57815",
"c7400e894f919f00a828259291ee56adce7fe853",
"a46c6ff36d580e75c74149e78db81e45131c7eb8",
"d9240c9ae99f2d8e865d3a976e129d7914385af6",
"a31f7060e5c5a82e7332e2ec7520038e47de3514",
"6abbd39926f37545ed9981b6130018cf8325d1c2",
"15b50ce6a544bdb7d22e124d486eeb933456f87e",
"14c204a11fafcfcfc7511a1e5ad2df6a74ca11c7",
"d973fd42f2e04bdf8f9c33f5ddba2497a5c750cd",
"efb8de27280ad63f9947575754845af611643c6a",
"d13f47b2a47383f92cf9817478d256355646a9f3",
"593f576ab4690f694e0116a56df22f91b82e7ca1",
"8060181b9f53854a86516fcf28dcd6cdb8f7c864",
"fae518bca280d0141846821683a58adc0aa8c21a",
"fb4a4e0079261e5671a75ccf4397cfa6ef9ac3d3",
"260b1a428cb719b02bbba1bf50f16b5666c59760",
"66799e221183265d47d63de9b3c5654ec6fd32db",
"508cf4f68cf3830cc256457700528ca1cb3726c9",
"27865a26b27cd861029ec68fa7da6a33bb8bda5c",
"dc7d67c1e2da5d32227ef4788af885c4b9298f19",
"e88839851919c731b6d0d0eaf361bafc2b7e34ec",
"5654f08841828e3b724032d57d3a09703f0463ef",
"1b9906db099c8edd0781058994ecab90d1d0a3c7",
"b456d3a401abf5314598cbede49c4fb2864bdf6f",
"3bd5589b1a7484c2b72ce98da4054b917c123bf0",
"885f4999dad83a9ca290567a2cbcecfa8ba64ee8",
"0974a4a164666cc9d64aace1df996b34174aefcb",
"0141313b35ef40c5abd12e3b2728d91d052d1c8b",
"6ed3ab914d9e028dbb54b84a6d66730955106a2a",
"3898fece082e0088c8f8fcb385617265f196125a",
"6b143f5f8f3ae21a96929abcff9d9ec644cd4c1c",
"c30f137bb126f97f90caa1bbf8d9462110e1f752",
"2d79eecd66605bad30680cc39f40410f4742bbef",
"aea7fb0e423da08aadcc4efee40040d314f8bfe4",
"2ea9a911afd97c6e78212ebca10fda0b04fe9a46",
"df5c8c7d4fc05c8454341132fa6c2038781507c1",
"67a8ee9e86884b6e908c971720b51d85acc5b4ff",
"f91ef2963e4da79dccbcc11e4fb1792f6b857107",
"f418b5268c135ae296659f91e87eb07b6f35330d",
"d0fdd0b6a3e12e6a402055df22a2dedd494bc730",
"b953e9f6b57089c162773fa9384b1a3d7df148a5",
"8a3133e137c7f5012e0dd5da63645c3dffdac690",
"26e3c0fbff1f016a41cd335289a6067fb02f5f94",
"693f0a2c440d966b0d57841d1ae0a9247c443001",
"62aaec5f53bd41c69a7051929f2c732b682d842e",
"85b092872d932f863251350b7dd3996bcb04524d",
"70e199dd09ea46055924d2a94eaef44a83c679c2",
"f823916ea4863576dcbb23e16c432fa4d1c6ae0a",
"0acf5fe90037e8116e731eab556cc4ed5adf55c1",
"7368e389427bc49e29e0554405c17f5c11c3c8de",
"1241bbb4e89bf3d559c139aff87f8bc981bc055b",
"3366535c9d8b2ed123bd50d15468aa41d02bd9fc",
"5cb4d5cd7629d30e95413d91356d1182d34383f1",
"41bff1b3bb9913c29355095f013503ef7a84bc2e",
"840fc496b8a07a99ccacbe4ed3d592c9016beb62",
"60cc0a8d01881c11b35263b3be91b63c98ffb4a1",
"de381cb378f45f8cce3dbf99d1b72c360dc095b2",
"f639192dc6ccd2c584e0f738fcb834b4f8cf59ed",
"8a61aece01fedbda0ff8aae2ce58f823ce787348",
"b1f174817cbacfc120572da60f64569665812578",
"49765c961ebcd043e89cc5ada097ca26beff4ba9",
"0e0ff38ff7c1bd57f343432cff6001c414b2154b",
"a41f67d9ef64bed30c581b8de39c19ba3d2726f7",
"4869fe26e261392e5a9ac8c00e4ab2b23cfa09e1",
"0e54c4a293793a4b863288c018d3fda85e61c336",
"1edab8c9a68ee30f7ff8e72d968d154209053b7d",
"2a0643cf1caf336f37a2180d2f30b9e74efc835b",
"fe00ed7ca7baaa330c371b69566c1a22a4df4830",
"3119294367d8382868babb9e02e5a2f5a4212590",
"f24590afe218b67793e90a8d2c1e77a64f7c8237",
"3a7cef8ceafd66d6f5b0057d64e950e30dc39f6e",
"dcfd4814248b005d8f9ef98ee3cd9feeec4e0cd3",
"2d847914022631c5871f18a53cf9844ad621175a",
"21950e1cae8e2e4e28dc0193ceab15694331b912",
"8811fa97d48e677cae7c0c0225667c37048022b8",
"170417f974af9707ed58b5ee14d000e1b5ad5899",
"af28a0ca07c2a0601e39b14fe3054ecb3f9a3bbc",
"18dacbb48c934818630dfbee93e6d405687fca69",
"edd70b701eee72cb63dac3ed1919ede2c64c0b20",
"b827c6bc54d2b47b7ff26c1cbe05e78168798c63",
"f92308cf2564f780b4bdd4a103dbf961076faefa",
"e593191ae2f1261743bab2c548792d643394d3c8",
"16a01a42bfad7328ac84cffd5c2707f774c9f3ff",
"4634913b66bfc5bc82f354ced8ac059808d45615",
"ff7e9ded1707aeba59d4c5db2795a0805c003413",
"c9162121b078f036405e9c4fd9358789e20259a2",
"45ccbde226b2a9e47c0c7b11cd29b201dd356635",
"dfa7ba1df52a2fa0e335f17810c175f361c3868c",
"6b6f087c14a80cc7becbfb6ef5e953c5558a4182",
"b27313bc5c703c8a25343176c620c8652b815abc",
"eb701be033610992ed0a1a845e4ab9098dbd53bd",
"8ed55a19253b9c8943c38dcd922c68c4471e7e0e",
"329ccbb304967dbdb440c69f3a7ffa5d3f0e83a8",
"1459e4a57f3f9f007d6b008c3d0f8de6dc8d1dc7",
"37847d4c63333bb984eb9bc7cb8be70da4d564b4",
"ff81b1a6ed0bbc02d2e89520bcddde5cb979e4b4",
"fb63b1c15d72d95b299fad70aa6f4546a5574acb",
"bed69ddca9cd5f844ea332f36ebe2b344456a823",
"1a1e63d99858f6c67c41d360361c01d887a19c34",
"f73389fc626e561cd4ece48c5103ef2e14c84dcc",
"d6e8f0c53e4176e6f9ada51b260b025825779c96",
"369fc7637cb7e68a02f115bc6dfd69be15058a09",
"11b32725c8822ba78ac4387bf6b6ddc6b9d32e95",
"45e87a63b94fb2fbc5daba6be68877f8f9b535ee",
"e4ab523669d6f90537665a2a4ee0ed05f5a05d34",
"8b010c27a2a92d360bd5e4da3b8d2298ca9886cc",
"0f3212a1b2d35e848672d8543b9ae721437b5476",
"613e3e526937188a7323354b145b602693073339",
"2e6c9827a91066b410a9404aa1c7f1ea7db798ab",
"e32e28f8b4ce082bf078106e4556741a9133d54c",
"0d0d354d557f5c13ef836c5d5c3001998ee8ba1c",
"ba9c5997b7151f3018013e793674049e2ae9522d",
"e33661738c9aeb689f691e84fbf15387fe334238",
"33870572d4e0df488839066b513fd26947b8d234",
"63ff4717dc19f874a8beaefbd2c5dbfe8b992008",
"22360f8c25f4d02ca2a72fdf2425a780a4c2ebbd",
"d4e073fe4e8de49462b54b7d3b15bec0140b94dc",
"e7006080955f069d23f86888ac02f092e90405c5",
"e325fa8621210b22a4937f52ae39b141d45eed1d",
"b25c2e452b161aa000c3a0d8b58bd53090244fe2",
"1e948485beaa216b2261d9d5fb58e8c43cdef078",
"074b0e55c138231fed8777aad45689de882d72d6",
"8c701dc908575b622b36620d0c96e08ee552e09a",
"9418a20caef73bb0888a42c5462b4b19ed1af6cd",
"bb099faa4f6e6219f4cb61efbbe3ccd9011c4ae6",
"765823c686caa89db0b76c19595189ac1fde4e8e",
"cb576cf8c33974e8acd59271f84af5aed3b3aded",
"a6782ac2d67062729861ae7bad06d0d5c946e3a2",
"48f44f4af54cc97c0c68e657ca077e84d52f4b2f",
"ec064891cd2523a28dd0b2dabdb8b7c2cb3cda25",
"e9ef0f4aa4b53a3f896ea9a06e14f8c367f8e00d",
"5502676aa7ceb599c2434534d566567746f58a3f",
"50a97d9add1f436e36cc58cf7ef6e2789b4826c8",
"06566dac6f5551c62c6509a11aa0da565ef93bd0",
"df5cf4023b3f108ae1ebc842f0784360e69505b5",
"3b88e13e911de2080572011ab319b6da432f7b40",
"c2b6fefb8e9cce9acb42563a68564129b0c7b573",
"dd16ed780e7a91305ffbc944aee348672f432cc6",
"8e7d53aa9a0c047860a686760916042ff00fd134",
"a3077d5b1562c26a7f4510e74b19bb485df18a58",
"0d652d78e993c371f5bad5d002529535624879b6",
"78344f8a9f438426c71c1b831e67584fd857a9a4",
"0eb37431ffe8286df6e0f012047d587b242ff876",
"64708954ca5e3d561693e44d61169f14a16d09ba",
"a3f8305eb437caa29a65a24a3ec5ab0f0cc80d0e",
"0319bbb9035f0fe73ab8a7bd8f3791b5ca95b9c9",
"431a38994496ee9d9d5a785065a68a7ea10c471f",
"3d803b249804637b73d74252a7e16ca80d3ae849",
"547fdcc03bf7a83f17e676a9305e1d61be98e7b3",
"6bbdc574f0d298a178e9f06f07652af290a5eaeb",
"92648f934e270a076b6f3867a039060bcf8cd9bb",
"520fb61230f1eca9bb3dceacfc7229fb24758647",
"75139a6f0279a2d282ff9ccfa3309286ce9658e9",
"d335e1f3a5a9e5e47eec76a0155304c7b80fcac6",
"16822ff84ee14561576572780e3f8662b92e5458",
"5d20316c57a142bafef7123e19a8889c37321673",
"5c3f3c65f97771adcaa51d35e201d04b1773475f",
"91404e4c37357c3781e0c6b4746e38ad0a075d05",
"ff7338de17e2ebf7325d3b01ad4a526bcd152a02",
"e86e061a121495fb6318b8f5b87c2600421c0930",
"6578fedfbbdbe783e81ebf00858b6ceeb920cb17",
"d2202a07abea26078e8c4157a85c94e967449a4e",
"65763a2ad25de626a20166d4fcf44d24e0ccb789",
"13bea902b231aec910cd49453d5b8d6582971294",
"0cae3c0967bd670764dd42d38e25f23485f53bf1",
"f526465f1b3b18cb0ce920cf25b7dd12b7c5819d",
"738d0dcbadfaad76a83ec38830c10370b6ee83d1",
"4652f309b41c6a70b44b1fed0657e925940eb660",
"fd91cf4d28bd370a6c5beb9ca158e4d91432df25",
"1c9670b90f05ead0285413435e4ac35512581008",
"474d21741eb104ecead31e93608f346ae851b350",
"97f122c4512fbc5ea0b04a11db01d0d2d0977527",
"21533f37ebde5fda1dc56594ff0e6f546736cc3a",
"56a61b61c90098d0c21d5480f3eb6511207de5b7",
"5f731fad0ece36f67b24e6c2d983b132a1449496",
"b60569d3cb32ccff3a3af78d1cc8b38e7f1216a7",
"0e14dacb995191be3eef42054d393d78dc9c4a9c",
"0361ca38187bd43dd74396c8ae6df437d7444f37",
"0a673bc55236eeabf67f311e6ea923fd38947ad1",
"d01028502ea9212abf4198d00e0c79edf58be33a",
"de6bb8fdb0b4f7082e8d1bc0de293bdb049a2f4f",
"5d7bf9f663978f3b661f66bf750090434fe479ba",
"c2dd778183717d4b7e009ea4210996168df4fec2",
"22c7945e7be7de5f5dde45fc7a66bc49fd076f18",
"a4be8f4fa967f87ce8f724cf7449b69ee7200a5b",
"02f5596c05c7c33fce30769abac3be05de4783d3",
"c25450d3109db0c8d03411d3305738fc16f1aada",
"3af53626f06e13fac7c7abd640ee63a7d90f8dc0",
"f2d4b9acc29b5149ffbafe6e254827ebdf3006dc",
"478b61f875dc79ec71e9b0b54df0304ec30a020a",
"15070c4074372bf898fdda49cb6e405361359c8e",
"01ab91db869a6c022ca5dd99c3708823d3bcec81",
"aa8394a83839c9c08088eced868178fb4b364c5e",
"eeaf380067f9ad14d5d0fbe26b0cc052fa052c6b",
"c400961cec340b8caa6eee4489c07596326ee5a5",
"e6baeab0c9be8e99decb4dbc9b4b10879d7bd93b",
"37d6c03026e3bcd497df30168df5d850b559b29d",
"e41d67544c15ad49915f9a6d28b30df6f1841939",
"ac60069a33f0c76e3b6e7ec6c928f0a42363a153",
"e18f01cab4e151bf3f9c404b1769e3835dddb02f",
"ac06e319cde3a332a3868a780763af76288e6c22",
"4722b9b417015ac0171d0bd3ebbcbcf9b376f433",
"4176d62e38f174c72e24e7f411f2bf9960a2fa42",
"664aa570e6ec1f948142da1b44032d465c118836",
"b8c2f2a647274869ef51a6ea576e6de8b2e4523a",
"366e61a0535b7ad71ec04487d0039a08a2e1f092",
"5fa677c5fbc1a79d2d712a82117f2ece85c1e786",
"4bf15bf7ca867baa5e9d838d3fadd9036fb933b4",
"cfc386ed0e47c6d8b35455ab5a64674d2d4c7824",
"45a457872416281f60b1e115b08c4220cd4ec14b",
"8e8997693718c21e577323f689bcf422ab8079f0",
"376adde1f9566f1d081010a977dfc4ce1ff20e78",
"29507b550d6dcea5082baf1f5049ef93b8cc34a8",
"5a46ded318d127413f26306e4198579f945abc10",
"95e3b9673d5721d63be1fc60abb0ae201be9be79",
"216f48b7f100ce3158a77c6c4de0324937f42493",
"76ba25268d9ce094d5e00a3aec0b62146e799f32",
"2d55ffba81942e9c239497dd52cc246f57bb1d1b",
"8d8751655f1fbf990244d53fe0110731c68da07a",
"90237e8e9d28d6b325a31a6a99339ae57a5ad777",
"0c41de143317d34c6d71a0365e3c0bf7939d45d0",
"94cd7658b1c08d8819ab836154e82d772979eb92",
"c267ff71f1e81077d4f59b47ccc5050a101348ee",
"a1674600e94a6b6bb9fb31a0a3e523b5d2a9f743",
"ae5982cd6b085ba5b766a742abe6a93d1969abac",
"d8711a8d43dc919fe39ae4b7c2f7b24667f5d470",
"8202495e24b9dd00b4d2f422bd02b0dc83927ccc",
"fc951b82c65c58a126e5220c37fc103be540ed53",
"f72b448114753222985c1574461f1ee0e7062dfd",
"a9c0152a99539653819beec0b80ecae2aac4ce21",
"51dced480853442d085747c262d2778a8e82ab26",
"39239fea512da7bbe2b15160dec90a2e21e81b77",
"dc709da33f7d374bee2a96fecc0650513ab5d1cd",
"ad48514dddb849dcf707b6533729b0eb1ea0283b",
"5ccd74aa8a041d5bd6f2c1cad5f71dd5204c1782",
"7d68df86d18ed2e2698289cf2e424ab9b5472b6c",
"1f711b394a48dd74849ebdaa00f8e15fc87395b6",
"4142d85178d6b79b4d5255e3560a85e937ca8f82",
"e7cc32a2788b8284557de0a698e68ab0fbf0d72d",
"dd7d86abb0910bf484d3508043ffabde7714fe65",
"87ae8cfb62bb5d2ddf9b65813f012f08af3c1edf",
"f9c722c16046a372553ab39d96c41077a8320e56",
"103ee4e23dea3b48ce9c5c305ad58f0ae4a7b633",
"4caafa9ce2161c93d42e6476deb7a8edd54cd9f6",
"fd1237b2dba203d54a327c245edaa0abe425520d",
"f8ee109aaaa2c82f29b8b71c8ec5f9d52658a51c",
"ff9903bf968754c47f4a6012173fe76bfeea364a",
"1dfaab6b4dd77828323379e2d59c904210ec2d29",
"eef813fd46f0b179964b6911a59861e3fbf5bfb2",
"7037b52474a9d38293c04bb5580a37dd112bdbf9",
"d758c4f203c205c08fc822181d6f4df9d1320607",
"a5d85a0d244675eca2d3e1b867aba56656d2124d",
"35ce6663c15c84a9995bdbee82bad163a41c2a4b",
"8da6363cb3ab523e367b852dfb259214bc91d0bf",
"d249937a613ec669fe2ad51fd8d858d9a61eb35a",
"c1d4e87d25785697218fa4280f85635c6d6bab12",
"b29321dbf7999ec7ec9b7ac9192071e512ada407",
"1d9ee81b6deae8e97afd55acf0c480a7ef85653d",
"8508eab8faddb8d02148db6255b1d52479c78b4a",
"293a76948fb2d72a85c5902e8ecca681fd5db9ff",
"2ff6bf2fc47b191d614c95f4f6b20a448927dc1a",
"c49412a73fef2233473f9ffe5fd62b12301c52f4",
"6fe5dfa3c95f2532f9327e1d0bde7e4f12f57a75",
"f4dff1708511ccf5de8ca55197416c47bfcf1eb2",
"e0241050f8fb77a1623cb76f8913fc6b031c3a93",
"3e2cf83f9b3cc5753e75c44fc58d293d011e1d59",
"091154faed43debcc159e7e74120e43ef43f0144",
"03496992008ed60d1a2f429687ec54d3e85365cb",
"ca0abc4356e4c48f9ef6ae4d0e74a79b5c08afc3",
"b5a00dfc4c67010f6da1b14c4a2dc32cd3a9453c",
"6bedb1256c4416af79a8ea633fa4e967371244f4",
"c20421b0c6587e5d6c90ea0682abbd12734b817d",
"0886ab0a3cb6c5e1461b033ddd911bd9d26ef7d2",
"1326774d4f335ac01f065857f87c7c1ea96c9b42",
"448ef678338ee9a074e3eef0366dd275da06979c",
"0bfc3f59ee383966cdd7a50fbba4509497921991",
"649d59f1431305be37d46b0416506092d13987d4",
"76eb7c08a16365ed56fe6842ddc489bb132c8e94",
"b004fd8afbdf176717f4e03bd9730bcf14eab8be",
"44a3a09e5cb7ccdab0f06e91433da8c02a91534e",
"0e6fae5a037dcef2f0a29ae8739e0e234ffc8af8",
"3bfea696426f929d60dcbdf8ee136e45c0b7c20f",
"024218014b88a097015e32a4fe7c059969ef01ce",
"694bd345d920e4e8549a36e6dff3afb9d69e6e26",
"5a48cdf507884eca0850beccfa2aa0df94af1e95",
"ac12a4deeeeb7522335ff0bf1c0a4a5c256c1722",
"362f26a0c8bfe08ca3711a2f85603c6d279bf78a",
"4a99e18562763d3138cf03e7ddf260c50915ca4e",
"2667569a6d75b093d2af7ae9adabb23b4cd3f35d",
"e757750398570cd058dc4a3c0cef4c147fa6c53b",
"7c7379c7333880c0bb6e0f264ea1d5a5d71187dd",
"b1c92f4a0d3c5e545010012c9f3f11c8146a86bb",
"e268e75280ef54929e9cf4427c455b958980638e",
"1fa49796ffc0716020cca8e87c7c0ae9c61b5c68",
"3e9c3d2679d8f336ed5cbdd89647761403222bfe",
"730eaa00caa14aa987a665585ccfef63d07a2363",
"83547f9c8abf1ac4b3405bad9ca9f130ffd0566a",
"60fc50644fd6bf3fc8833d434777852ea17c2bea",
"44298df48f603f0b2df9aa4343d6ded1e5277b34",
"0ecd8fb0741cbb93e8e451d9404a6630372967ad",
"12a91bd0ae5f5de3a096ab4aaac735fe61e8a6e9",
"f111681dd6fa9f3bf4cba09db33946e7dc6cab55",
"182c9592c07fd478fa0256df5c699963d178fc8f",
"3b20d45d80e6dbcc1649f9628d32270586530122",
"b809bd3d736d51c517afdaeb867a69668d76f864",
"3a9c8b7144d42183f82462807345f3c88bdacc16",
"df25e9a2a58d47c026de236a46bd48444d0025f4",
"ccbfe5b6fa4dd341d371b63a304b5e55abe3c7be",
"10fe2ae299ee384d572290554e3dff9bf74471d6",
"5428420f2761695c94769c2c2dd26f496cccd0ff",
"7a08a1d45906b81cfd70c23ea3024d989d1d768c",
"8d1bf9e99710931b4b05207cf4fdbd059ba1a1c6",
"3ea7541d552f6b6207f571a86f26109149e7f8ac",
"045d201916f5cb680731f94fa8407d2ad26edfb7",
"7d72b160874af0c029241f7b97df65987b41cd62",
"fed4e84dd7d7b3d1cca268bf53e801409a06a4a1",
"a2da673c3132801795a0adf3af7ab01575a0ad21",
"969219c51d2462d2d37b449ef728693525e86e02",
"6346931ce2bd8fd3ec87c2b4e83efd02da401589",
"d6cebf613f7be0d5d06fa55e10301e46a2bf1705",
"a28594316612733b536d8d0146e9fd3d47be6276",
"671c1692442170429cb7bdd2ddcc6480ee4e71ad",
"86feebe4d813a420c55ba7d9e57c2371637b406e",
"d74535a5a51433bf35bd4c4f11ff6441989f4fef",
"7f8526ff766bb0a4a8a13b415ec8d547927c8683",
"fd3a6583d0a39535aed9d941aca3799b3707596e",
"5a4d0fff3fe3107441b93a7812ccfbffe11ed445",
"d55861572d21d6a055efebe535152244ce238fd3",
"fb44af965324634cb741c40118abb80db004b2a0",
"027ccb943e75ce289d2f4e7a069703d89def6d53",
"33547c9c3c13db20ee72c1446c878b3df651179c",
"0468a1a7576f2534ad99f1b7e7dc680cd7bd63b5",
"442e8a7128fa131920ec003013c406af3f93da35",
"ff56843fcc37310a66a307d5d5319ee6cf592376",
"2ff5ad97f3ceccd6309488ac94fd2f99a4ad2c68",
"bf8653b6c20af5a28a23c6ea05ce0cf811b7d72a",
"4bac839e0afc85182c644c4e666ac8f759966598",
"9fd352719603a384058029aa4373637596fdf260",
"866755374058f1bbfcdf209c7788fc5755b14ad1",
"6f17a4db67206748b5fe8f812920efaf9b7427ac",
"04e95b45fcf46544c7629d1dc2286b6c6713f232",
"11d10b4e473a99d005365b04f3633b79d513a38e",
"f11991737fcc3ab3ff7c06324030dd124bac31c4",
"a16be2451791e0798851ca67bc810854215c93f4",
"26ee6d26dc19a9aa868eadf84f35e41b13dc83ab",
"9120db4ddbd196b697bc385c80dd4a529f7d190c",
"189eb3f2018daba128463c3b9f4705f932608adf",
"75bf7beeddbf24fe88f079f8b77e00ff3076b775",
"b51d491ad9f9e5efa12606adbc0daf52e9a905ca",
"bd0482622393556cdcdc32cfab7fdea4fbf64ab5",
"f26adabdbff401e14e174c2d8254c9178a41a7a8",
"3b49a7911b50f1002fe5c724ec4d6e657e833325",
"ea03e8a38bb9e7837f5a54129ed094df82a6d6be",
"92a14b671f5c4ed99618dd38f8bf60bb6987660a",
"327ebd4d2a65b95f4eee9b412401af007a7bfad0",
"82d190f64f8297944a10f2feb829b96b0ed53bb1",
"3e87e5f9eb08f79e6797f7f541bdf47ada3a0979",
"2598886018db208ddc04a68a3e160daa93ddd7f0",
"e13bf0b75b387a62ef1351008c23bd074d2ffd8f",
"95b002926748bf267a65af79fde8cd7b7b15983c",
"38c9f0a1c0b335cb4b83126f767a926f11e06335",
"1bde528a1b41b2e538988ada9443e459a503a90b",
"f7799e1474fcad718e3f290b8574bb3ad58b7e1c",
"d79e97cf3b86c0816904bfe41642af0238b33dfd",
"256471fa5e139f63bb85657b0dd60d2d4149cb0a",
"0381aa32813e0a7fe7e64c2a43fc81bf663ba287",
"0f52af8b2e0ec208944f6623eeff0c6a7b014163",
"f0ef4efe6cb0e5d9d19ae46afb6f062e83dd0953",
"52222939ae0e732c96b530287a99db79efe59411",
"594b63197c34c418d2e0cfc75dbdc29b96b74512",
"a0695005f5ff937dfa9ee6c39cde8e15872cd766",
"8325eb69d7cc8d33eac0cf04a94c4d03073c204b",
"80c1e45a9900baced069dee93dd293fe2bc072b7",
"3ce1e1147ae634c3c0bcb01d1be303c122c8f16e",
"85fad7aee043ca217ccc88dbb4651704611058f4",
"ceb1f8e70097149c881a846b623e6c97319e493e",
"708e202dcc227197a48a52e186111f3a29dc875b",
"0d98b84861c3f98f3f7286070e68e454f6f421f6",
"b2f9ca61d554926c7700bda0dfcbb710ff042a54",
"f41f0927784ad5f76a9699e0e35c643eed0b643b",
"94bef619447cc8ba20afa2b4ed8a849c20f49a3f",
"bb07e255717893c588c5faaca6652d06450f7d11",
"4b2bc365efbbd723f33031e467d85fc36e73ad5b",
"636d9e55eeb61ecfe712c69d3d4a313321403245",
"51b372ecad512fe752bf11ebde11d2f5c373077b",
"d0e24bd0ce73629bbffd72467ce776143c53e631",
"c99497eb2151ef41bde39b72c7287808f80f63de",
"cb79ebef769761f61faee142600226fcce950add",
"a8f0329391232f15d670548c3d987afbcf075902",
"0e7ffcc9167b2b549c86ef0da30f388a94811589",
"d9dd28b3474c90f32659077c43c116aad60bb994",
"56e41fadd91bd66af82ffa666b48c17b539cb8bd",
"9729a2355971d13b7d8a51a012918a65fcc8ad73",
"3e05939d14f16a4ccc20840849d09903f684bb51",
"18616a16bd46186e6ed08020c3abd68bfd4deb7c",
"17651e259dc05f74d9ff8c8530c04a681b1a77d0",
"8c92282578dd99580bf4f01d365bddd04e9b4115",
"992878fab486e7e86d276b555dab392979283a5e",
"eecea67ffd1bf3ae16c3a85df274d1dca5a78421",
"97f076e3cf36ac994742d3056f5e211744dcaa2c",
"489370dcbd5aa7d8d8b60fe53bb6274f66222378",
"bda5d6f0803e1c78c78d84460ce899f28a7b2176",
"a05de1fbf3902aa895b95cc8020ba0ab0efabc7e",
"ac3a03fea6cae9d115a117da3aa9ebe1b12af26b",
"273ce2744abbf56fc5e2e10a28547c9d8578432e",
"f4257eb9537b3a7077562d9907f3f2432fdf4ca8",
"ea4294c79f64a2a5739b1fca98d98427b91846a3",
"8205f8ad4e26167a014add81b2cdd323ff32eabe",
"31647521fa35643dbc1143752cd2b003922dd1b7",
"267aba59016e312039a0724a1e98f89712b2adfc",
"7cbfde1e9b3166900fd5c33a9d2dc208182a27a7",
"f3d513783ce9d2b75373c6a1a7cadc2b3055c769",
"9db63a88019a26d088949c4c27a37725f0ad20f3",
"c8e548fb1d3e0dfffb66427235e62605873a4388",
"097b5b4ca40ecfd3c3dba9c6462bcb863d0f93e3",
"eeec2008e88cd047f6188e9b4459f548e1cd01ce",
"89b9eb53b76adf9e38e0da5a15bf810f8d72a3c8",
"0f47dc9057d79572414c94399f8ef8d19dd91b4d",
"3d40a606f78f6b13e7617ad8eaea6d32801d73a3",
"c1face7cd82eefebb309d723e609f16538ba3992",
"f999a62da2e78f9210fe4403b76e91957b8cf646",
"7d1e3d489bfaa47874b79907250188cb54cf8a7c",
"414477a31676d5e75efa7f3e8dc6624bcf2b2e52",
"992e94ebe4125513e4587ef4ecc00b8ef2247b1e",
"f1821e0b99b9081b7579baef94945620a699f352",
"505dd9ea9684380289944a297540e2c134b193bf",
"b33893741fa77f2ae258216feae665b1d3f7e3f0",
"9db91e976ed679e136a08b28cee626cb72a39a87",
"33461e4be19d750852dd9c7bd49c1db849d228a4",
"6b44955cd95c12f4bad9bbbb012086d7bdec871d",
"ed4c266a51cd696ec7dd7a223920ec9a0fbc9857",
"9e50d9053a82ccf3ad4466002a07f6c7f0feba1d",
"b6fa4a4b2aae4bffbf0a5e2e9337770e2e6e4da9",
"c3e14c346b761ddb05d056ea986e77a75b7baaeb",
"cf37950828edf1d9614a3d1eeb705cd3a6f5d41f",
"0b7f169c8bcd51a5e01a83ec2a00fe5aea31207c",
"8404b5925dc3ab73f162eaf1365cf7d312513be0",
"6417a71e08c3d5ec1501656d53203e82dd12fd55",
"3f389f37ea8739d39e8068a52f3f309a0c141e93",
"b20f81eb0cd190e23477fc7acd5ba2f2b148027b",
"87f47cdc67658ae3d5b274b3c20cc24ee3292c90",
"c618c3e44334ea85d725816b2ae5dcb8fcf62687",
"adf6312a55b7f42f391cc650b5c7fd4aaa769104",
"f78e010c556d5dcc1b43378c746df2f617a33b32",
"6e08f0be593cdea9b37799bad48207e0eb1ee8d6",
"db0ceddf6b36d58e33d476b6cc15f871d1282514",
"d73d48584846f445c60c7370a15f7dd89ba2801e",
"91efbd9630dce10517f189f33b6533a70d45cdbf",
"8907ddb8a5169baf305e759963a5bea8dae935c2",
"c9aaaec2eeb2ac12eeda6b936eb40e34752bccd1",
"fa15ca59f18ad6c4714cd47b592e0d0f6628cdbc",
"973f618cd366ccaf2742aaadd21556523b7b8dd2",
"7c41c5edffa368f1a7a7f44d820fc67a57dd49fa",
"6fb6cff70825fbac2aef72722181d39c9cd4113e",
"af99d6f47aa4d6bbc0bf1e48c588397e5f1594db",
"a629f91b1e4fc249ce2a41e82eb2a2f9a716fd79",
"a32101ab75c10defdd3f8854f44a6c362bbf3ccd",
"b030e9ea80763b8120a264288da32af7cdbdabd9",
"a5746b4f08bac6eac67dc2ca4259abe33b4cc3d2",
"6b62f5bb28637c2b358ef7ca961c0ca0b5726af8",
"da9d63b284bf9186eb7145641c7504646a0125a1",
"fe8953ab8b18857bebc42006ac3d06f3669a1fec",
"d3f4189324b11a48416cb00941fd3c84ab5bab27",
"4438a1049844dffd140ef18eb389e872f1bfe7c4",
"8dba01d6aeca3563279157835cb715941e959be6",
"40eb6f2a6ee3ce531bf95f71cdf3882d72c101cb",
"bfea229850a382dc2f9670b59c9aa8825c87f4f2",
"577a232a687bd826a0fdd4aeecef7ef10ac328aa",
"6c1e2d0ddd36316d1dc2ea331db92c4fdf76e4a1",
"63fc06c81744ce28183c61b6978892711fbdcc6a",
"8e3b629178221f8adcb13f09b9703a7c7dc28990",
"564886b165a72d06668672d9e3da99023d687c5b",
"00ea587c6d48dce671189e56472a18cd12fc76fe",
"c427f41379a210774a086162828729687df825d3",
"71cf289c52aa92af8c232072f889b08770205e35",
"e103ffbb95159c58e4f6d7c24db3dec1fed98b86",
"654a21b2b38efb85742423538dee110fbc356f01",
"f2d31aa9c072f2f6967fefaf990723b57be202a0",
"dd97ac8384dae651bb7689943c5fb36b6b481991",
"a9d1a71f7acfd6772357d4be533c6a3ce8e400e4",
"1455810d57102f122942d8e9d3166fa24d2488bb",
"b4c3bee39d8c0103378e99ae74bd6a373bcd0723",
"241c41a63294d7f33f53fa2541ac7ba7abcd9549",
"fc724a2333040ced38f87aa4c70149ffab095bb7",
"f9980f720538a62ef654b5b1ab5296663a77c6c3",
"c51585dbf9847fffbbc05c4b416360391db4eeb4",
"db8ec5735fd64b027344da5e66306cc5c8f1685f",
"ab74e54949cc23485d64354c5da3a825bd8bd6ee",
"73221e43d781f17aa8ef1830f10b56c14a3d93a5",
"b6c1560a0a40ec76d3efc6349d806d26b855b99c",
"d331389ada13decc046efa655410d52ec27d996f",
"791c378d4e6d0e3f878e2f0569d627ebb313ca19",
"897f4c525092a9dd7de400ee91978f8f3a572501",
"bd4efee8974636a48cc79651d5b9fc2240218996",
"62867d26bddbc415d11673a053ec0350f2fd9905",
"5ccf38079c7a3b51b83105acd6fe83d97a8f8ec0",
"8f57d6070619f82c990f85b266db62a2e38b1b68",
"cf1acf7e24738f6e2833d5cd62432f18c381bf3a",
"d40f40b9af75782dad15f83b61330b3dac4ed232",
"ed1120f3eb4b25aa416afbaa4f14b90ff10f396e",
"2c0cdcd1c5466cf48ea6c73cdd6f8d1e14fa4b5e",
"a49eec9892e6f1a1811cf862f4d5297fc599ba84",
"ebfd445034150956866bff17a861c0808e1ec9a0",
"88c545bfdda8bae8a1ad463730a8ce99b0fc7c37",
"c46bc0cc82472ef615d8c45de0e54da78925da42",
"fdfe1d508b44f6fa5687b4bf82ac1bce25f553c8",
"17e3c975fb16fcf980953645b465c1550bf20fdf",
"c4a66c20d0b73cfd61e8e25da730e524ee8ae796",
"cf6890f6f1d7b6c3905670a71a24ff72bfa5c7a9",
"af7a7ada3ee12e42ef0bd96a8dc6876771440052",
"41b9b46d99fb36a40b456ddd27f645fbf900d121",
"70779ec14870222af11ff1dbb075ece63d558450",
"98ee9c46a9bebe3ad43da688811201b6e41beb2f",
"5828b917f9bb9f3251284ef7f73036f1c4d28a44",
"bd436d436936c72996d4dc051ace39dd04316940",
"05d70903267d8c55886e73da8c2cfed32e82ce92",
"caaa7581e69534dd7137269f0d24ef718f450156",
"40c58b45ed5b41b7776d1ecf920309f3a3aa1c39",
"b558c742e681345f5895e99d35338d90a10723cd",
"9b6ede8fc507d34ec777746f6712f4e8d30435df",
"cf8113765c8485379a1c91749359a890c434a0b5",
"cf80f246b387f7805dcfc806abda53d9c156725e",
"13998dcf46026c31a8eaff1c2b52089d28644a3b",
"fdd6bca31118ea0a40675890c06c047333ab2ac1",
"de8e92d48cb4810ca7323f4468504d7968dd1a02",
"0337574750db4437cfc024b06d73864a4147e6e6",
"cd12741bf205fc69d7ccb96b5ff2fe66a1f947ca",
"413238a1e0ca08f504c5db2289fdf1f32fa182d2",
"94427ee22ba796cde7b065975545e9439b13d3d4",
"29b933e485c3950ebc9d51538a81a222558a2a51",
"3ee76c289177c0ab91d8367805fe31165b0589ee",
"b80fc5437c6e772039a0eb66963bdd547a345a73",
"3ae037f84e430d1b1ac9991e856b4773bcdbf750",
"9c77332cba279b4aada915ceabcaadf4484feede",
"273736991071f640732e333a45541a9504282b77",
"7266729924c6ea2e4ca756b4054cc413711304c1",
"f7aac06a8fc449975ff4c74c33f1d349e9961684",
"49a6dacd7565ed1407c49a28412894f3b5e1b6ae",
"646376828d0520035246ccbbfcb82127160cd184",
"8e5627d28a3e05380c1c405fa8d65822a9a75cfe",
"4f062ef2c66c1c3d7a91083247acbd610245591b",
"b33fb2a33d73c40e953629a21b6b1778fa42e08a",
"f8aa1daedb391069847c66e14b2da6cc2e5669ae",
"9f1896e07f8e5c966113f47bcd081c85e5ba9718",
"6e90444406fb86d90883a7d2dd6c1ed4d38f7855",
"166f7e7cc24db6556847fdc7cedbe360851cad29",
"34a2d1a9dc92b9fe74d31b590d7f74d738c31d73",
"aacacf872fceb6b051a940341a4ce71de10be0e8",
"0df724a58f2b8760ac438f5ebf2e5791fa22d2d6",
"adbf6f5bf5e5c9584304d0c839d7015d5f273e64",
"db38f2df76977168fa5621c395e1956c176fdec1",
"1168f2ddb5e402d906eb20e2101b366302e7e286",
"c7a955e9fef5efd664cb3d06fb34b71c1e74f455",
"821a6b6c08440dc7fdce85a03889c9843283c26d",
"7fddc70a57834b9479f429d5962a9020d219dfa0",
"1e8f5b225959e4166a767c8c0be0cad75af09701",
"e937cdd79acca6178e54e365c491f2d9de2b0268",
"3b015a9325cd77da23ecca0de5e102680fe1fbe9",
"546b402467335dfc2d6c2fa01c3e3a5c72e2799a",
"b82584617b4b6595d958e678502a99f405e70a11",
"5902236d0a4b2ee92058ffc7f4294d5fa526eb5d",
"39be7db1e90ba4361db37c40360b63c66b1d5c75",
"0302701c98c7572e39ce345a76413dc6db65a30e",
"d476d35887c640f5537c4796a4f788546d3259e7",
"8c02a8116e77b58fa22bdb148e958967b9e5652d",
"0e491fae79fe163a763c5c8efae47a94b1e423f3",
"e408b0d62cfed949b9fb1506a3d2056bd6d56735",
"c3a5aced07d230f3ec909533a9e6d68b88a1246c",
"fb635d80c391e12c1de80842da92c53e97b5c01e",
"ad63583bee62015e59b073c904cd96aed2f52cd1",
"ed985f6fe0cdc1a204e28ff3890a8f7963a32921",
"f322305f86ed4a8288f86f861313c51afab80e91",
"1f837c65723eb6afbcdb6f0be3ac882e6586d27a",
"900796956cef71b858dfcc2513a29cf3b9a2cf65",
"267b0ed31213b30c7a7943af6b94e57d6cbe639d",
"94899f7be23a345be12973c57f48cda52a3f56a8",
"5fb5df2e616946e00cc76d04f19097b54b64bffe",
"488468991cee53520b4bf81d2566babd731b2635",
"85df6136820827bf2679c23477e7563e292a11dd",
"cb3b7a3765680a1a940cca530443526816849493",
"e972cda2c473cb430b30f70d6223ea90037c2bba",
"9000a626d766a845d4cd1ebef3992da731abf7c7",
"fb2c388a5de1e732d9692811e05e8a552ad4a963",
"a5ee494fda700b0d7a92e83f41ae78bda9c2c87c",
"54dc34d4b95cecae167aaca508b9f1e42cd589db",
"35f22ba37af1b96499b83566fd69dfe50d4441b9",
"be5c9c9258fe8fb8d283cd9d9a2f8b06d12bfa3e",
"c8c44c884cd58c1eff7597d02f1ccf36f70cddf3",
"e69be6051d9178a2a626f02e04e13f21114178d0",
"8c22012d61597e39e05342bf36b450bae4b7d341",
"44f3984159e630b3b6be1cc159c7a00b099086a6",
"05d2487a47afba3bf2ab3aabd13d74ddf2f8bcd8",
"793c0850941fef7f8b48d9b70ed59281fb3f69ff",
"02304875ce4a03ef1e40e22673b80136804e0619",
"82d858314fd194a56e38692e9e5540602b732274",
"077c040c08c8cad87fc183b8c2eb2dca7626722a",
"dd7e3923b528d19deef76fdbbe7a43489af71a10",
"9d244b221a167c1c2bacbd00ecefc1a44ecab552",
"de71c5d9b12d362a72a0dea943c01fe8d21c4b9e",
"43bd5fca00fe5a711ebc56b23bb8bc9e855f1435",
"5f59493c702ca57442659f8eae27384ec514698a",
"2a687502c55803b6a20a77538fc5ef6b39d047f5",
"892f02bc43e4e06764f08e842cff037c3abe6c58",
"e4b44370d3b4c4a377c8bdd15db62a5d12dd1a55",
"411c54a604accb05f3b2013a67468bc72f140221",
"796ae2f96ace2b6bec5ba5b10a2296f2c9f50cc1",
"432e6aafbb6c59c1484d3e5f880d9027460f67f6",
"7cb7d3a4a27ab33c91c7041896e5573c80fbc00e",
"1bb6f9a921b797e90699a0c1a6217b16dd5ce5c9",
"de24a04621b8cbb2164b67f609d2848ecde99cf7",
"68aca5dd65b08a41c96b1841bf106f14108fdf70",
"207030d2e15547a95e6142a2f4746312b153e61d",
"c70dc71b18ec5ec211e87bfce6b66e07413349a3",
"c0b92d25fbc4e0fde7ea2654fca401c0c7f5519a",
"06a92d52d9d8dbc61a2405eb5985c65982b08146",
"5c0505e221eb96028d1a92566832cb59d580507d",
"0a93fa833ebbf650d7cd284f13b353eee393cc54",
"11da344e3a04ed20ca527945e2c832addd4facf0",
"97a2f8c1df19d816ee904895f0aba24870c1d9ff",
"5ea8505000dea690699258e78ad16e2009af3fa6",
"f9dbd590a40aeceab30198327f4d846aed5400b9",
"34b15f9f16d95de3f78e32ca4610280fdf16eb6c",
"2606372a142c65d9bb29eb5b80dbaeeaa9354933",
"6ca1c896100ca906f650e87812662a5937520b26",
"f290f6b4a5ff1f33ef543791dd1f879cb75b0917",
"c1b6ceb1410c062e94f3b25a0832d00c0b35d953",
"be5afcc60091d16b119e019cbb913430ff80f90c",
"158f1ff7faef7f1ba8fd4485cdcc2ef67203d0b5",
"e584bd6c1cbb5c8bb9b74a856f6fdd7c22392efe",
"7e1b2b6222ab5b3c98d97ca20b47996d7d961022",
"ef0628c48e85d55feea03632831b3e418d67a9ec",
"b04451a1bd4f9fc3ef312d15a96f99d9b6a26c68",
"2b5552546c6dc637aaa282a990083df8a4a0c0c0",
"5477a3615f30a3d945fb90fbdcece5be00852471",
"b57a4606f656a24d7682b5826016b264dd2df2cd",
"efe5ff6ddddeef266708a8a922f018ec7c48152c",
"a1e1e04fd95282d215ed3fe7435defb40442ef81",
"8e26e4c046801831dedf710aa254deb825c26d14",
"a7d2fa95cd50bb102cb264981010d6bae82d5a47",
"71561a8e12951001410a942178c9aede81457ccd",
"011923f1dff08562b79b5d6ae902e5301fc08044",
"0f81f8a7aabbee5a6bbd75d0a7004931fdd15dae",
"feedf345a36c0f39e67fbd5f3fabc65c5425ac16",
"950fae209d954ba946e74ed4990077b99da197ce",
"89fcc6de1cc4ebdadf3b3c8542f0b6464090cfc0",
"8cbc3c240359798f5617774fc7a1f798086ff1ff",
"76d23a3fa919738f65fa84981c9d9560e150cf1d",
"b9ed0bc4cb61807adbdab559cbe3b1ae47d9a70c",
"ff52ea7223235925d3044c976c18ecee0e4a56f6",
"f5a161e4fe97d768b9436aca02c5b10fc3b74bc6",
"b29ce1a22298449f7e838821ec7afbef6157ae81",
"97f7064094d97ae694ce926d310cf7db6ec4a9e0",
"3b0d83884646a4840e833eb727b469e84968a4a5",
"ee513ccf7ec9ac813af332d7bc5057fc3c5c1db0",
"7919c7ea61baa42f8b353ac577fb9749975ce2ac",
"867eea5c38704f34a38b285f0c1b0c99918c4706",
"72c99b79394656d788ad10030c49b2ce41d30ade",
"e7c929898a462aba736864532faef8810dfee466",
"88fc4f178259397b2f1cc4a055dd0ed3596ae1ff",
"6b674a38c163d5de1982e87406e920f01fc3e96d",
"b257f482cbad5e0382c182fdb01bb129377672f3",
"9535467ff53024289c3f084174b6341a32bb2cbe",
"881e9af2191a5d545ef62f43d43f0a396e649362",
"540c56cac6c0753d5d8a9057fc7d3596b172807a",
"99c1e2ac52ed89c5441bb9bfd63f840a432380fa",
"602299734a592373cb41ae2949b804ea060fc9e5",
"3ae826dee28839af341f221beedbc34f96986a42",
"3e7761740fa2a39c53e1593ed9a37f5984870920",
"b461950d59f55fccb8cf4bfed1d7c99fb9444018",
"c673f5db6818bc93d33674ebe833645f944133bd",
"7087288cfbc762d92757768973987096a23d66f5",
"8c7c2242cc47cf093078728a6b9f640c88970b96",
"2f1a18470e39e3aaef5083017e9524955a285588",
"27d0c8f23589c75117c7a6a185f48ad3fde8aa2a",
"5f4c6edee448fc89bf5bc67631abcce82a2d5a27",
"42b4d95f93f0cc9e0e798bc3354bd73fd29509ae",
"bd7c5a0daa7594cbde84c1ebdf7ccef06ba1aeee",
"bdc0ab9881e7489bcb207b050fd28bb877e53ce5",
"93ba7f593cd0443a7ff38dff0f12797806115a8d",
"488f043226678111449f379741aed730316930ec",
"e1986e45701972d4630284f095aec6c6bf4178ac",
"b2dbf12862e4f24dc291b1126598c0769c96a74a",
"a57b33c785878884c1164c55d5963e277a145d69",
"5c491284dd02a482f2fe906add42c046da778cd9",
"f1de61ad8897a845f2be49e3e2b2951bc678b678",
"02c07d7be167f3e57efa40c68e63d3184c657087",
"0087a4b50c904018ece9fbc1bf1178ba9dea5cc9",
"ac812d78342fc8c3a45ffe69aaaae5b8c0720de7",
"b108342faba43dedafa1e1ef75e3c86ab6e016d9",
"69ac8be8fdf5941d3149b0950468bdc17b8143d3",
"9177e67de681900247772aecd330d60061408a4c",
"f01735bef6ac944a2e9a3802217d8dd6092adf9e",
"c138cd062c8251a67c0ca784251ae5d7503501b4",
"054655d79b822ebeb5ab78ec506c59cb82a5271d",
"f66ecd4ece5b48ffbe4481aa905a43ad35b6a2a4",
"803d36f0f61fb13e9ff4920f9fb82a98c17f4735",
"11288424572995351fe88128f958b6d9e159b513",
"ed9900b5aca79568dfd9fd8a29ef7fa075eace15",
"2c3e7cc2c90c5999224f596f5b4d4e73a19141bc",
"d59c422b9d05d48dd4f81d9f2c56d4f1587d7c66",
"f5f36191d9320e7d570b0c5ce29d791878db70e1",
"7bdedd0ffd6c22c53b61ff432612121e7469c9ba",
"2ceb39553e0e3f3c898c00c1a035bd56d62be14c",
"7d588fc7abd2e7285b30e78550aa10a985c8a99f",
"c861244ab81f452dc01717490574332db4b54e5f",
"037ff39894c0abfc9363c7823647cda56a53ad9c",
"2649e9c6fe72d9ef148f9e76bad6883866c0bb75",
"a8531eff36e3a68c4809ea62f5fe380918949825",
"b542ddcd6c44f8e1768222f4cf2daee06c8c98aa",
"abb288e7428daef0ddf034150cfc9668d5fadf57",
"45e31a51920452c65ad5368a74425d0fe37e51f1",
"af3ea6a11a99543046a5a4396d48743cf8c33cac",
"3c202564bf81a3a3ce5ad19e4625a6bb17fc9f9b",
"215abde9e67241f7724d9d779d199bbdddfa7cb4",
"98f09130bbbd027d5712a6787234e5caaf5059b6",
"b4ddb31cf3e9a63cd18dd99f4ee0e506a5c2af98",
"d9f878bc45f693a38559bc70faa6062187aa9059",
"58eeb3ab9111dcc1ec5f7bb10ad85192a74cf63b",
"3d0a68eeb50de4d347c6fd43894d058c5a4da84e",
"34064ef8b596b02f1ae28c2fc6135c58e960c96c",
"3f48c2c516797cf5c174fc266e2263a07f04f567",
"c1ba45fcd83aecdecbdb05a60e412dc1f448ae1c",
"4552c1f2966615de0de21bf8d88d06cd68f2302c",
"88ffc02c5e84225f19424f8f59b108d8cf459fd0",
"1cb89868305760a2c8ee536a5e34efeedcbe2c7b",
"98f7fe1db8ade2f8db2b314ba9f41c7f2ebbfde9",
"050b3acb2e9ee3b51bd07e09b3be3630c751c92d",
"c1a749e09e71883b36bec2c44752446376497c16",
"03b94c81a08efd70ff8876865b61754dcad8230a",
"498a5c4e4a07bac289fcfafbad603bbb347dcf79",
"3aa105afdac236b73a7da59d4271b3b9ff1aeb38",
"99bd62d27610a778faf790688ff7c0866e06273c",
"0726c553dac48490d44f67716dd398e093b68d3c",
"258d2d35e4363fdc650fca88f6839fd0ed019458",
"a0910f75931306f5cca0ab9ee7ef9f426c8016a2",
"507a41d22f9c9b93cd079492c7432a2976a7fd24",
"f1a6a86689ce6a5b6fb59b8c299ee4a05e28c144",
"be77eebc3d623bca34e1548e091f966e002504cf",
"ac23f45d9b880421270b9b5bde5ac11352218c23",
"7d5347b74f283566246741cd2ec0d917ad27da98",
"b92dc59204cd87d10c9f019621d8e91934b98c6b",
"aac00590646ba790015a9f3b8234a2181d124404",
"33d8c351891c2737a340617800eafc3596b7ccc7",
"23cf44f4c7ee46d68d1312be19f394b87ff4a661",
"02be3341441eb9dac2df3b6e6945f136ff81423a",
"d9e1055067429ab8ba2650c9874dd5fabe8d97f5",
"a5811e43a74043e3bf1e706720bac3ec01b079c4",
"f07a875ce1e672b45f7401a38056b598d17d1935",
"deeb160c2d0af1679c68f16a683e9aa0e76fe637",
"be95222fb5d3294598270b93214252edd78e15a6",
"026dfbde5d8f48394fa7648e8b3a3b361f37dd69",
"5e955d39d032920758bf921614c867fed746486c",
"bb3787258a22f6830daf9b9fea242eb16018db65",
"e01838a70a2e19d747a49085db6445b1b823901e",
"405c00b91d04275e7f49a98cbff57fb001ba57e3",
"798485dfb160af78bf8aec87110f5b148b0ff7d3",
"30e9d6103c40a65b4b0ecc20b322c1e40484c956",
"8279ef72fd6cc7b3623ee6ad01ee5e695eff375c",
"fdad6358fce828763a712cea63fa0738636b111e",
"cdc3c8a2652a84ec9aa0eea41b3c2da76c4718fd",
"0334064f525c0fc43948cbc63ee7fc4727391157",
"0a9bb23e4e0e8586156d289042665e6f52d174af",
"a3f4c2ec674ea0e1de090903a53065d2133ff4f5",
"59ff46e49cd04056f4dfdd6b0b48df2372cd022b",
"ccbcdd49984891a973018d6d30477d386ffc0e28",
"57fbc1ed46984fec0992a07539e049d89a3d0224",
"f065bce876c6326f9144bef6834fcfe88bef6172",
"b1012014fe58f93d5b4b1a78ff41b97f34ffb7f0",
"b4f44f39f2c5df4b4ca0115f3d8575ae27f288c4",
"5acfeb2b7992b4b0f6b45269db6737e5bb8a8a02",
"963ad3c3d77806611e98bcbd7a778aca5d0adddb",
"c888f40660b6ad1d3a37bfd4e1f7a855d96605f7",
"d324eab377d44c1b15c30562e9751421f13a9659",
"fd5ac7f6afdc0bece1311f66d39277c7aae21855",
"fea14ff7b336cc300b5554f7eec9828a3cdcd78f",
"ef950d515a086615f37d1bf14a95481ec332fa26",
"ec2e7d7ee167776ca8d50b873b0da95ee6a68d28",
"e6f56ff3bc89366c3801b27cfc49bce75dc986c6",
"bb135b64b3b1f615740aafe05690f6ad78ca2e2f",
"1f06f5340f81ea8815dae06cb9828da649518cd8",
"b78790622fb2b1cb4e7243da191cb8a856472031",
"3aff91f9b7815ce698195f10fcb5cb6d7cdb0d94",
"87ff1990c03962a87c71591761b3cc335e26bf52",
"a0588460f3f07894b783e0c5903330e120a89311",
"2295bb4ea4ad41df84fa2fd1c754d08ebb678582",
"f5cb86dabd1bd285e6fd99689e0369996b248fcb",
"079c193d0c820ed6d16899ed539df89bd462d20f",
"8318b07d89414df3479652383e9dcad185910bc4",
"1e4cff4a0fb5cfa861c1b719500ef44cb385246a",
"73b7db10fe3bc95cdb12f5eac7b1adafcac6ec95",
"9243b9fdeb4b700c5f820ce0d7df3db385a50598",
"3bc07195f5cee586cd9949ad9414807f4fcce726",
"d25c47ad0ebc0a9c7618f17378ba284a38b6e8f0",
"7e55ed346a1b848c55253059d95c45ed838a6418",
"067b53215401a90e4554287e196c438c5715e7a6",
"723cdcf2336b12a47b570853fdfa4cf03ef01d3e",
"b9484b6832f660b102f80c7a4a2efbaa3487d1ca",
"7ec903d712e634f37df3d129ee9a940f5b720205",
"4ea67250eaa67ab1b3be7b90f9acd252553317e6",
"f33e79f14be741adebb76de3f47ea991f7ce3ce5",
"3d04849b7b7b31d6cf7785cd6804a9f821f12a99",
"df9346fefbde0a2b10f21d6c0a0b2c9c4b890bc2",
"3bedb4438e511faec67b14e199cc27a24e5e2ce5",
"97d4729fa47d6d2026538ad711e6ac07b9170b46",
"be9def8b11d22756d818bf7fabead3886b53d64f",
"d31968509da970f8d124e3b9a2e79e281206cdcd",
"72cb2fd713544c4f0f42a393e9c9ec2d9e3d916d",
"741f7c96519ea8115e8d1d9c2d77797574c1712e",
"63e72488473741c516feb19a25b0e1753c3f1152",
"1aba9812c701dbdddc84485cc8589e3f788bbd96",
"592b0047a43457f59dda4eaa64001152eb398648",
"8f8eacc0785941276c37bf10003d9b02b7ce68f9",
"54bcb91339f133e8e4cbe74482c4afe8cadf20f3",
"284aadc37c028087283f5a8b61fc5805979f506f",
"a6d59b3c0eeafe2d6fdff4b58e067c087c552a71",
"6d420813f5d2499d67c881f76f2fbb69a571c4c2",
"438ae8430433153bcdb98e84837fe90ac636b67d",
"7962ac0a8e9304f39ae20c8095a2511a601f2ff4",
"897d439f95b0081995145e478cbe5bc71cc4fcc4",
"eedf08031d2a7bd9c4ec81b0088c91a7154328f8",
"dec7979644302e978356ce9d65cfcb095e4c48e7",
"66f0f87933f799539ca4520a991a6844585fd3b1",
"a407c3a4f822889a5df73396d3c7a0257cfe164b",
"08334f790ba788ad7716fe3e31ec6a1206efe3da",
"b7b33acbdf4bb5af004a138c248f165604843d4c",
"dfc6e974f28493938ffd18c69437507e0dfd3158",
"a8bca9cd927edad446bfcf9ff8826ff71ddca3d7",
"a6066e3ac3ff2d84a6987d9efa469f32c40d64ac",
"1eb2a5ab9d0f5747f8e4e579691659a8bd8b789d",
"03bc9d84d692f2957eddf3baaf83ef328b83d597",
"3682ef195b349c7752eb025f562f459284def238",
"a50329eb43364616ceb276d0f97226914aa1b2f7",
"329af88ca622d7d26db91778ecbef89101ff225a",
"cf0d55fb119f619ad081934ac5238536d111c202",
"947c89a398f5c06c0544072bbd23618fa7b63a8e",
"a7b1c19746d280551f6bd8fce9ca8fa2872d8d1d",
"e49226c50023e012657c022009d58489054d6f99",
"b7d0479b5c98c984d2957ddf5efed978e2771512",
"67f9c3554d388605adf8aca6c4a7a56cf0262939",
"139f095d515643ee822b16c146a6e0cf0406d3c4",
"2f42bc942cb124d8f8b05e1adb8a90a289cab9ba",
"5ee1f42b6a04f372147a24e233471d9ddc6e0096",
"c568feb700d2bab0ea9693df3bd08c9c1fdeb06e",
"911c194fb3ceb8ead034baaff0fa5c4f9ce4fecc",
"49cd26c0b3d7cd71f6dda79d0626bfbf00626dc6",
"bf22cea01471f0e95fd7ecbb6288fb7c4e3f7d8f",
"86e56d20530658706eae8d1415707ed181c6bc52",
"70260236b28bc29b6a67f8bb613b1b7b46506850",
"57fcb117fc3f87ac34e947862fc9f86de218689f",
"2f07b76fcbec54e1fb691d00c8858750726c6ddd",
"86a38e208b65f868db455e02a5c7ae43401c1d14",
"f6177f85fe5cd76dd46190b10766bb2510b3b1fd",
"f193d7d6ccb8e1176723448d17dda91fc2a584ad",
"2f1ea7f8dae064dc873256e425cdf8e926cd674b",
"9ec7a0a2ceb73c03c9e2ce31a1584a1472798408",
"aa05f676f7acdd747b8f7593b8f57bc38e53a5b9",
"d7170ff9e7b2865cfdfc4b09b80b2ed252e1781e",
"adaed6a3ac4232b96e7ec93882821f75a9118adb",
"bd1b4ac5c1e5e23ae73617eb2704b5dd55c4aaae",
"94be0ca3921ce2ac80c6d16a0a563afba63f29a3",
"61fe352ad9ff955a428bf498459a19761e4b5cab",
"260863f571c66c6c2d2a374ae001b8400a8dae2e",
"83f2f2b5a5d3169b6b5f340fd7c7dd9a4ea7405b",
"c0590a100dac4383fafc55f7571890f44c727983",
"873ce895ae0110ed9055a537f03f9b0455baff1c",
"6b67e0571ebb0c69100ac4b9218e893668b7b925",
"946d6ac6755a78a0b1e7bb41b3efdb824c9e9945",
"edef49d1ef58c5ee5766d933081f83fdce739bf2",
"1f55d7a32750b3e63c56aad00370411b90420a29",
"9017c591100945497a7196d76d35d0a4f8865690",
"4307478718896f45620f9f9a4c9339cd1e13a7fb",
"f1217713afef991ba698ccdf3c6284de71ec49f2",
"e47d7ca2aab86c69266a03c0dec6e56f5500095c",
"c68a5a88578e99db539da28301bfef1c3247472e",
"f26674a5a9745b3e11fd297a5a2fbfdbb1d49904",
"b32ae984ce87dba7f5732aa3c5119e0791d45190",
"ac3ee5f7090daf85080f1998f5f669c4ab796825",
"9186d1f30fc59cfcfba0a0b46e030cfbc54926b7",
"294ae8fd240a0716fdce4da85b6399aec6ec7868",
"4abb24fecaaf73cd5c5082a4e3259748647a61da",
"aa02c52a2f8df67e8f069319bc56d9080eff0711",
"909b99bb7cab6bc56ba3e120cc1630e1b40295aa",
"f90f714fcfbe15f82416aaff04472d36919b73dd",
"24f1de980e5e37d8b040551efa1eb179a491b38e",
"0b3a32627b10b505d7bc3caef0aee348eb7a8d5a",
"90f20f447a43647a94888eab410aa550fc808642",
"036442af878b220ce2bcad4b986198759a14fbd8",
"e5e1ba583f41d9eb529132b8e00421a533bb7be1",
"335fcbca89e4ffe0bd2c63690814429ab6ad9915",
"bdbf1111630116d487317e2a7cfac8123d4730fb",
"edafe055b467bda7dbbb56c082e12c93fe7975f6",
"c183f80a229c25d59656d4c910f1c771ea0fba01",
"d309f593b1ac8640e05c8c122f51d832ed259d61",
"b37fef9f22c484ae561d5ea02e6b875e8ea339b5",
"8735719ecc8b02765132b88e15082f097c1f568c",
"98c156610905e04a2d3ee862b64e7974ea21383f",
"e7f26371262c0bfee25a3ee2ebd1585f701f3c7a",
"c676d8b99a9127b6516ebeb2067a979244d549be",
"b7c1f091fa9549b1ebbab4a1fcb27ab763ee61bc",
"3ba7a022072d1d09efd5ad7606b110a1d1e6488f",
"7b8bb08b0868b91cdcc77338e9138426c62aefb9",
"a100f1c683c05349866c301b4e243d80bf4d578b",
"46951b1b42b4550d0cd9f82e6f7138627bc55266",
"d4d40b14922d93067012110d8d42357462bbb129",
"fb8020e58255042acc348ce769257e63c88afb0b",
"5d2be57cd9fd8ce1698dd5c65f660f945d5c125c",
"de0e54a186f3b7fa4116b5d39d4cef556dcf64e3",
"56f9af650e24f5077f6ff24ea21148152415bbae",
"06d658dba496b8f53fd318d35ed7b4133e70e672",
"96d1ce5da665ee88cacbc73f35f871d8231255e2",
"66d76d7ab26a69b176f7c8ce5788a53c106e0491",
"5f80ee96711ac922cc108a3e851d0fb6712d4d22",
"7c9ee0f911324306d11c0f25d84ef79dfb730aae",
"1007756238a18909c95d00bf7484101e87097683",
"db3568db2fd364f04c5cc4545c9a660765e80649",
"207d2133f97241894a156d7913592d1dd91663bb",
"c33aa8758989e7d96fd35146697224cf72b803a7",
"e63f33489055962845c70976bd9a40d0d84c6b1c",
"ca69fdc4fa532aef074b62fb9a765e38d1db298b",
"f9c81ab3829724cf1ebe346d07dc2ccda44c958d",
"cc246992324f85d25ec229c713618f281d7ed563",
"fa3c155865c74a5637dab10c2245081138067133",
"4e0efa4690c5486d918f615763dda1dd8b022090",
"81a1ee5cc24d92987749716a692cc65da81f66fb",
"6c0c7b29692dbdb0b26ac25e67337b51842c3574",
"e8a2432f9dd41b4f56fdabdfbff57d8d45e33500",
"f6e8a18b15d0d934f0b9ed0b2cdcd437ac47e8fa",
"d6467fe4f19ecf3afa7ea8b0ab7b118317445bf2",
"ff79347eb01e203ce0be380da43103c1bd3d6598",
"bcef784ad4d1efd995021efbdb6e447196a474c4",
"eb92ac9036937feae8ed022f692d4178290565b4",
"ce11d69f233d5bf6ec0bce2f02489946e0f2fb28",
"64ce15dbe236a16624c0a3af19f06c88774cf7a3",
"d061afdab11ab6135c860f5288ad9d80faf1af17",
"86beae2ebb25810b8005d9a111c45bd2113ab948",
"fe60305455ad490ed3f1978e5e4db8fb4b78e8c8",
"3a2584b5443a9d6b34e133ac378b8521f77f62fa",
"60d95ebbd8b5440e0a1099733a97d541c6f9c80b",
"15f183ac7df0d579608aa903cf14afdd20912b4c",
"b3faba715ba1cff2f9f3961d48550c2b5db3e69c",
"919e36ab1fe33e563f87d94075cd11ba3b5683d7",
"3af2c53bb220a312c0869d292fbbbdb2e472ce37",
"dd7052926a1ae263731aa9a3b82ca323f9f49276",
"5a47023ac085c0e66599cdc005eb74dd19116623",
"0dc34dc15d596f2118b4eaa63949e8f41fc5c0a2",
"b82e1864b5e788b0a06c39d1b170bdcda2f1eed3",
"252b6cd7bc4d3667f336c2c478c319485bd8715e",
"f140c6d28eb41454173c8a5d8685381afc3639fa",
"e83d47ff451e276013fd46d2dc426ee8b24828d5",
"1a5b68c2b3d47928cf1331e09b8e2a4546c95a69",
"2230c8ddc4f91b7b16810dc164b1c2b89f871754",
"b015b29f3488e3925c07afaa9afd008e1985ca08",
"63614e9c947212e4d598f8d7ace9c802f08ec3e5",
"41309538fb4d43fd07ed3ff87e94d462099eba15",
"be789a487fe16a0061aa5bccdcd4465aeed74c08",
"09a8b46f343f1666933ed0bd086a5f8eb2a7815c",
"c5225c64cdcf5fe48830d069f2bf5c04a1c27c7c",
"c7d5ffe51b82ebeece2486c03e61400d3ecf774d",
"1b00e8a4133e7854059b361d3552586968450dce",
"b96f357c2ebca53da84c23c9d4d979cbbdf110e8",
"e5e8a403fca4017485999e8f2f0d14e809dd217c",
"b4902d34088378c9555f6f0f4e40d863c415f6aa",
"84c3cf4cf13915508bbcfa333ccec30adda2b8a8",
"dea7082a6f4b14a232a924ba577e85ca2ba8f6e4",
"77e0a176bdffb2b2995334bca583f9caaa5846ad",
"6f8511c3600ac7254b8550b29a892e6632ca29fb",
"acd7aeb9c9041fa40d4df4a4f2a0a0a5d65992ab",
"da55e521a179d3a56a2e3d8e1fde464078b8ccf3",
"c597b6989e449ce0d3293a4abf229e175f97b32e",
"5532d40aae29d1c66266afd51867f389d20f055b",
"86e6fa22a1ee0f1e298fdbbee7b73cb5f2f95ea1",
"a79c95283b5d3794e57c90f88b8c6a014853a378",
"fee02969100846ace2daa80f9d49b95d618fcac1",
"b79e2f5b5627ada642528431e481a027e4ce77dc",
"d18b67ba21c33ec7ef0bfa7febb9546a242e8f00",
"d1360bbec0ff36caa2d5e6b2f0e2b47a5123a46f",
"171b5a45f7486515b00d9e530f730962e003170a",
"36ccab2d7a589d926c5c8711ea3428cfcf1e8cf3",
"cc33d04a7ba8ad181ca42b7ab307b8159df883de",
"cc64c1d80bfbd6e4126918ff40f51e6845b78df3",
"fa9a89caa3db0e22b6d98e34a09735e14bdf6fe2",
"550ad2b55828ab85c52a146f7767f79e6ebe03ee",
"7e8af47f59e5362c424dcd5cb9d075bd6a4a650a",
"0448441418579ef34259c18026ca1857b17e2a8f",
"01b7686659356abd60d71169cc54b05d80b238b6",
"681a8c9374a5ff39be3f09a2d6475f0638fe3361",
"01ad0fb31d77c32c5fb3434d543943848bb9938c",
"5526eceea020140a3c6604bb7e8e6a75e156d35e",
"8dc655758ed515ae159cad3cb768d04d785c2bb1",
"64862b3ab38843f5a68408aabfca716b300b4d16",
"0482757ce91cec74dddafaff44a4d6f342a47763",
"b11826b11396efa0802a0055f5a4d3128fce5da7",
"35f061746ce61e910219df6d5089a731c2ce4c36",
"21e47c7a340a530e61fa3bebf024169a0f540845",
"f5d06f61385adf5d43c2c3d580016e929ed06a6a",
"308112618fa492626a219981907c919e27c765ab",
"e258c72eca212f9379183262b1b3177e6c9da992",
"093bb686a45b9118a284b998281e480d4185bb8f",
"d6a95e4d583a7390c3afa118c7576591912e9206",
"1d798a80b4f957a454060d9533c94afbf33e0d9e",
"fd936becf18e8245f1acc6e98ec3507838650746",
"66d1f99a1eada49d1b043aab7b9535af193a34a3",
"03fd69f3231c5ff6e62384b3b8e2079e0231ad25",
"bdeebfb79ab230127191a0276d8f1573a8d54fd7",
"26fa16d2b2988117c06fcf184f4d86d4fd8fec53",
"3ec460056d6ff6c86b17bdae5adf656fe84301e8",
"664898d8c87aef3fc5fde24be0f015fde79bb46e",
"ee17f352185f40e43874faece5a0e22c95a8d839",
"2a6f3c4f556ed25008889587f621bff86711a70d",
"3e4854874574f733e181a2b4eada43b0adfeee01",
"13c9491e49481f9800b297c4077653f1d42efd84",
"983b2dc534a90f54bfc8f83c665c760deccd9826",
"008681a2caf40bab4878ca7703f2bb4fa2487952",
"4d77f95c217e862b05066360df47f8bb1695a709",
"e9ae5897f77097ba6214865084a9beca8b92de67",
"56fb4d67a925dbf4804c0cf11f201d8215133097",
"6b87eed670d17dd5c82ac925f159bb4e44648349",
"c620f873e5a907b5919c70c5b887a6a3a7085cb6",
"a985e067a51a9042282c6129a97375e5ecaaf7cc",
"b4bc032113ac663575f45c24421804b60737da7e",
"01047a494201e8159dfb553da8cec9dc56817b7a",
"89bdf59e8e6b7656eb4714d416d724ce67d58b35",
"dc21692ea377f8e081d8977d638b8e46c5dc4b7d",
"47d20003c0dee4a483d5b8c203d90adb0b29055c",
"dea268c389e891bc7f048362c766119f4a3b1928",
"5472931ff0ba947f62b4dd85bab7a32b8cc9c158",
"a74cb416c1661f5f9899fe34a02f26b26c85000a",
"186eb42145bfe40e384c2d20d0c4ba48fd9395c0",
"a496eeb84da629a6710080963bdfebbb8c65d6ef",
"12988da089bfd916e7eb6e11563a970a13825603",
"08811b4b875530f11186763a11cc23da855c9973",
"80401f89ae078d0414afc48d7f45da8eec246329",
"507bc2237a80ba9839e33ec1b465d2a44fb4bbbb",
"72ec0775c7fab75a5fe8d634e20ae11a73b5d309",
"4feb224b1aa2ca4ebd07ba45e900a407f0404e1f",
"503a6187435260f8b73fcacb06bb5f599f50434b",
"a9b38dc1aecf0ebe9f84489f359cc8650dbf4d74",
"f3d867af4d4192fab694404f9c4ba9f0e2fe1cb4",
"ff045e0813f912ef2b1177b2998e74902c6c1467",
"a91dcfb10034a02f35a1b1f1d57caa0d45daa414",
"1d51afad285943849653053282c8adc0dde78aa1",
"f05a040be65b7495855441fb13175841710b12e9",
"eb666265bee8a40f02bbafa1c0d3805e8ce2cc40",
"b0400984478df19c282496df8d36bf4cbedc7abd",
"ca1b1f445354d93f81da9d89ce3f83db12855c24",
"cb2d83daae7149c0077a92f8ea9a94923ba65f21",
"0bd213d15ae1d12603d2d21951723b66d14890ca",
"d6416c9be1f202a6156e4203c6c393689f569b05",
"4112b0fdc505d9a7e9cf24b1afa10fc2fba330e1",
"6b303bdc97ee3749413885fc6c49ca9a6e14becf",
"c829045b8dd3db49fa4b2732a04cd165d6bda2e3",
"c7ba5a7b3f1dc94d3d106564e779a7363cbe4a7b",
"a8dc065dce8b3083b440b7f68abd280b3aa8a611",
"609d05fff2073aac74eada5ff22a0bcd1e242a6c",
"8fe949b2a030b3e57018ccb243c775a69540d691",
"32cd94dd23ebe05288a151852d4e0e0cd752bcb2",
"223d36086ec861e181c43ee413a51baf141b2813",
"357fc79b41b6381266f81ab7e508bf4e85419816",
"5847ad2ff194301d2415e27ffbc58644d9f054a3",
"3aa7a5635bc2349e02a5146a19c14e108e3e219d",
"45c7f3049b1816613624a22198ca01366db8c6b2",
"f3c4a53e1eb50cd9f6fbf8eb82778bde397ee92e",
"58c26e1c9d2f69bb0176e3a008829c88ed52cf87",
"3af5a7084da77cf5b6559b0594b14680460500fc",
"dc791309887629e9e3fee74ecbd7b99375002889",
"6e8e1e09727aa9a4f3eae811e5d4617b212931c9",
"25a541ee0aa96323bc9ba05e98234ff372dc94ca",
"c7706156c607d5e732010eaa98191498bfcc4514",
"41f53f3faeaac73855f6060c1f9bd1e50803dbcc",
"092ccfdcbc895a73fd5c0efce378fbd5165b4386",
"577b6320562f361fe4c93029f79613a2bb02a3c5",
"a79ef67b2a6d391349064a6ba4b6fa6f8d875646",
"5494490c40e494c72eb8ed86fb4ed020d7862cca",
"f5212405c52a1390b3f0af63b4b482deeba84761",
"16b22d9178fa6a1aaf2ecb01ec97e067399c5286",
"25c982cd8c06ef1df0b785d7684bca7651d0bba8",
"6f3a598cc168479394b9e88c60ecd427f099f91b",
"7b7e83fbc75acb7e49315ace7df3278b0eba5dea",
"3c900f106f9a1bcbe14fb2830bf66cc39c6c7ab7",
"a8895aee80324a24f46f7448e88f75ecd207f2b6",
"c11f5b13bfd73bec3f0f2749aa0ca1b89018eae3",
"c0b0d29e19c0993098103a940f99be0d8aa4d76a",
"2a1154ef87fb35ef62550345762d7ee0b6dfebdb",
"3407c6c017ab959e1892904443e905f9de6ac61d",
"66493422c2d1f99d5ff9210f3ee8e72eb725a815",
"7c65f08cd1935bc811912913ee87359a7fd44d9f",
"5f4fc8236ee08ae279a1e09f033bfb5acddcf607",
"8b834a7b6e1b18c0ad7a2afba0acb6c20ae43c5f",
"19061244975c18e709e618176a4549d86131c8f1",
"2ec320acecd030e5c0040cf5a440980e21f6ebca",
"706fbc655087c504e101c3801f8937e90ac46b9e",
"961c18319ff9625258655316b23983ee6016db72",
"e6fd85f2494c3a90ab4f1af14d917605a7b432fc",
"111480cd6ef496b1a5bed2283b2a0f05181db77e",
"94f7675c72867de3bf97e4d5c42154f9fba87770",
"657a951df0c6b4de6417176e8295fc14fbe68742",
"617e0c1877235b4949a280a954ab127db3f3af2a",
"2f6cf9c7a5dd87a73b2156302d6cd6bdf5b57dbd",
"3bff9a9dc11764d9c5b5df18bec9b6e5be7c857f",
"10d8519101e34475c24ecb1b870ad7e29feb74b2",
"09c438f8fbf1bf33f5941ec0bbde228b21121a8a",
"156a3a576a2b882f73b490887fddbbe8b95a402d",
"f5e881b5a953a01d30521b8f91449fb4fd54ab10",
"c306392d13e4c2c4fc4d323966e4bdec8780d3a5",
"874386540aea3541545c4e214603953e3b8c7256",
"ae95b229f504cd4711905d203a31bf1a2e4c2cdb",
"1df5cf0c4528476038000fde4b7fea9a6e4a46ab",
"2499317589d61230cc03bb13af701d10862b4375",
"d3523ccf7836aaa1718e3d815f5706077c25ee28",
"fbd4fd9feaf1af27ef3a0ff2943d94fbce99a6b5",
"86ed10fca9a01a0f8f468c81bcea49827df79a22",
"14690d19513d144f54db64bf1232e8ca3e22cada",
"240825387d260b8415838af8987ec5870298403e",
"a2fc976ed6c290e4dc4f3283d0d7a382bf286a06",
"7936ba877394f2b03d7345b3f3c33e5fa9382868",
"d9517cc9667c81908fe565194ba8deddff6745fd",
"ba957250280262521ae7d6d3e6f7791834c173a7",
"a56d9008e6487b04e6faf01d5eb0e9653a0e567a",
"7c459719981b6b57c7eb6efd173f2d19da3e682d",
"45ea9cc97d1d5bfa3912a2cf04500e892b681aa1",
"4c1aa65f90526fb71b2898718609bb9734cf533e",
"07add86bb6bf729345aa28ac894d9f76e8f00751",
"0482f0ce0470c982c592779f055abe52d7aecdb2",
"c294f2ab5ca11382ad81a43bc6455ea275ecb309",
"8d80359c3841f1b82b8001520bf85853c8d516a1",
"a06ed9f6de015c79ba5a3a751c81801913e7514e",
"df15b497ab3e2333b18942da94464a9a8fdcdd6d",
"50dd817762ae53ba45bc4eac0e308580223d8875",
"a104f9681ca20567fdd14cf3858ac072d528e8cf",
"5ccf9a388af8b0f9ff0d73e8ede0b763ca9dce0a",
"6ef74c66747b6a9adf6056b87aad6df60a774933",
"fde0af09f76a607fa8173d31ecfe26aca7e686bf",
"d652df7c30787db00585c69da2f77be72dce6a94",
"832c6ad53f8ec6c3cda6965e49c8176a72d25a4f",
"78545c2f0f60c07e8b7315213366468964f3dec4",
"b8c2ab53163e184bd8e730c445b0930cb2a006c6",
"e909e04c6c22d37da5c39f86f873d607d372c024",
"77ee404e838849b7633db6e6e8f29879d1594cc1",
"2d52a53ce5e4f141148a5f770cfd3ead2d6a45b8",
"85ac8a1d4db5e0b4337e863485de94124858fa83",
"15f525299e05d508380f0b12ae639612f79cd241",
"efdc8c52c77fa6d3afbc602b9334a8f11cedf77f",
"fece740fcbf4871bad2c233e8d95a6e4a3b007cb",
"5b673c7440efc032807378e7fb555623b867f5fe",
"c8bff352296a54ade1b87260833726527d6eea1a",
"79c1372d3339c02b17b70ec3cec65c857a7ec89d",
"2acd999c16dc8f11e0cd69c70eaf7af27f95a0f4",
"af06ad645133f580a87895353508053c5de60716",
"e35ec2f715c8fa5bacff8249373682fc0e3a47ed",
"f9ad3ac155e4428986b1cd4689807fd8c3288ae3",
"48a5c75ae3257a830d43e2b845076557b2b07df1",
"f85a0426d7c41a312e005a9ce4024d7760613c8e",
"1da38708fc6f07ae9ae2f773b03b35c458afe371",
"b4dcc00fe3fd82d7b6cd074f06124506f9c7a825",
"85f9a1afc29df4f59aa507a743bda16f1798060f",
"27e39c0df5f1b624710874fa55ac0b26c8f2b64e",
"a20d16fc319dbbe35d8d407578c3b7577d86e800",
"c991c0eea00996250aa7c60595b6e9d41d8a75b8",
"ca2f766d19b54ffa76c8ad0fe97750b43642bf97",
"854b0ba3530aa58124ad52166bd1bc29277b980e",
"86059467036681b36a4b1f7952aaf55214f7a650",
"116eaa79e6367e5790569e54324ad98ecde71963",
"51e18c27fce03d536df9c797b289d364b6727368",
"a3bf5ab7c3c6df038bb49e72073a9e43f89ad92d",
"fcb1007f9d2f0873ab6f89c0445836c500f412b0",
"71698818496edab9bef8854553b5e97ca7a7e72a",
"1fa85f0da3d3b545f830b5f48b2e79ec7b34fec4",
"51f2d4e3fc17736740db6b7ea1f7d5fc31e90ed7",
"00ed8793af94c296896b1e472fd85ee196961f9d",
"62408234cfc5ffb8bbe38791c8eddb45dfe1d968",
"e382bc4eb9a2423c2be022025e2d5571a14102f0",
"c2b599f0683bca4ea16544502bc0999ab89225f3",
"f5bfb8d90a1a93ea2c888503e9948a91d9e9a8d2",
"a37424d72335fa41303ef78be66cf30b88ab420e",
"46501507beb069b053b4ff871a6d934da529c76a",
"d1ccf1b807252aa1e2c8f7e1eb693df72e20a043",
"d3d706bbf73671f8fa4c91525c31695b9b027db1",
"518e625d551d9cae8dcd6d8a043fab558a035e48",
"8760eee729f51e1a03aebba56d752c68f66f76f6",
"bc226a9c38e117e2c2ec5ca2776499087d86961c",
"2f07e39312a5d3c3913ba0eedecfd4df3e629614",
"4ad85838054621e30c9cc6d397e46168f3804109",
"fa4ac94829e3edc9b6289c0da99ce1fa8f6a0676",
"6353d6115b505f90e26336f6caba3e0d47513fda",
"84119b02656657fd7db9d8d042d00c02d7ca8215",
"73d62de0cc7af246093147bb00e4f4548b0c1808",
"3e9a4eedaed767999de09fd51754a132dc7c2e61",
"071465388c83b21778940c861a99c8c3f50f5261",
"5b86131257d3b5104bf55c45c235df7b4cae2daa",
"b72c3411f0c40ebc975d74bdfacd302e66a1d8c1",
"15e8a96948aca10c5a03e9f1acdb24f908cc730f",
"1017a2bc69d6bb1a42a3c35c52686cc9b1a2496f",
"2b6e20b50c36db5cc15a185ad89a64d697d1e8b8",
"8e160f170c7dbfa9e603c509d1f401e487a5806d",
"a925fb0e02672a754a3e3cb3dbd15b010210bb55",
"d3dd83447e56c0eeaa25eb1607a26f1e1ee2dd6a",
"381080a5a5247837ae107aa29afde9b9cbf752e6",
"79c89a239ad0b364fcfa2d072510f58e6e3fd0ce",
"d7a2520ad3ac89a593e92c7e17e06102905f5f8e",
"59ccfdda77b1ab76aeac2e4d7e5d8aa09407c3a0",
"38dc571f2e108e8775e5e2490baca6f03aaafccb",
"9cda5507a599c2026be79ef9de5d3ac07f6aead1",
"44664bddd58ef672eb00639022841db6d82bb27e",
"db176c06b5deb61363e810c6fb266c6890fac5bc",
"de8dcc50226d0b201eeb85cca789e59c6cc06ea4",
"651513c757f34898abd5d0dbedc1ddd4a1ac66a8",
"b265f1b4560d3682bcd9d17c1032ac6b18381f49",
"a47463a664afacdc8ee5df2d32842d4ce0bc8ec7",
"825bd3f5e1e4856b914d4446c05151ddf3904e78",
"a70a6822e0e598bc33cedf747a22630c70bf8538",
"db6932d58ca22165fe8a438da519f1eee897b530",
"cb4939fd752544fb962dcc7dab5843ee97d1f51b",
"1dec499e3d33fb4d80d4cc6d359c458f0c42f1d1",
"9d3030a0933aaf96125e1e5ea1683915ff867e2a",
"b3d3077ccc23cb994fd84b2d148fd12ead2c2679",
"c7f78eafb6218dbb53e45f7cd327e0fdb42b1140",
"927f062dc9cb1d68050f828d953b057f16325f86",
"c80ba01ed92d9217e4df85643f498acebcc9a908",
"46ee08aaf3d3e0c6e8edfc7fb643aa44eebfc48f",
"4e9b60dee0ca0d817b13275aa778ccaaa55b4351",
"09265eb3da221fe2dfb3e290f03b3e2d3f75db6c",
"c4c0e0413f6c1807bb6785b5c722a97de4dd0e8c",
"d273cd02475f26f8af80964f324c133a22cc2cf0",
"8fbcb519636f3066fc90686593fc5323d73e4e80",
"ec865ee9f4ab1cf21a3f6f85ecb46b6ac7a4cf23",
"ef2d09114ab602cce8d86f7f1dfb9658c8938270",
"7be6fe341459b1a0d666e6086ae83d083173bba8",
"078184b7d65a1c46d2f75a3a807b8b12e98ccca0",
"c3b7a6fbd7ad4c70484222306ffaa2ef25781363",
"910cd74294dc3f86851c04829bc73a37924caef1",
"e4e4d9dcaa17e0deb6f6f73df0a6abaca32be59a",
"a4d2232578e263d5c79befc49a5a7ae69a78e283",
"cd7421eb86c010323bbb12ecc745f75946fc402d",
"6e86218c3611d8e626b2e60b15ae4ea899a49855",
"6830a044d74a397f1ecd21adbe7c975c33d42ed4",
"14395ad8739dc159c105302396fb8531fa2f62dd",
"ff2bd185e7484d6bcbe82e40de17201099f3a5bd",
"400ba8d9352e79a6ab9a557d3758b07caed7075d",
"12dd6d4a5d04526e6a2fb7559c7d0becd93226ba",
"fc30dc26687862458a378901d3273e38a1b28c83",
"e663e8c516889c8da95f92c811eaf0f19b230d69",
"35b0af9a6833dbaf9089bd97ed98d386a8fd1256",
"993d88101cdc829fab7a48f1fa1f98c23b7807af",
"68099688e6c31ee3c836dd59d8e70689da573d82",
"3e173a18abcf0cfc2223d0a4afca887ec322a7b1",
"64cec32ac6119d3740fdbb182f4174a36a38e96f",
"e178ff40575c862f8faf1be045a673e8cb4b5e98",
"1057fb952c732f12cbd5b6a71ce6420d5d0c8dd1",
"77ced78b31d70f797892e57981a084d307891ef9",
"ad1f25b3f53ab0d2bb1ecd8b624ee8f701369b50",
"66d580019b36141927684949682639af06f79e4f",
"b78bbc4ecc0d867a1e800b95ff17d1af9bd71cb3",
"92f17d71c3e851174913a47f8c4addfaafa80c8d",
"a5a7af57b50c2c9ddaa5b278417f82e61deddc99",
"2c519f5b5f495a48ab7da8db64fa43c1583a1b6e",
"8a66cfa776bb563d136630fdc89096edc9495fae",
"45d6de80e8f90f18d5db347df79a5aa4472f9159",
"f18afb793c52fb5501546fe33a8d335aad8ba7b5",
"5c41af060f16d8c47bb4c26b881fec91c93fa268",
"5e0d4653c7e0c4114aea8e3a3d2b4948d6cf5b88",
"90486f3051d5386c4dcd492582384233215f50bf",
"e040ea5ec78571c4fe15cb812213c9fdfcece3c8",
"9ca982ee28ea7e08545d8a2dbe44fb7656919ac9",
"32591e6aa45a717bb5e44fe4406b9210d5426884",
"1ff8f625ff4922894a72d7d62290e125354b00d0",
"aa28e40f672fb60a16d8047ef16f573982c474e0",
"9873a364638732d72e7e24df0c0a63ecd9c6adee",
"9b3f5b9f3c9fd45a212fc53c041ccab371381290",
"e078706cd1382d8e01c505e77d06a18e9fd3ecba",
"38f4bb52d8a1f41a508e474d691c0b5cd6168ff0",
"15eed71588c359dc030f669434c8ad47bc103fc1",
"789c50ee3589eed1d9aa57373a17ac8c3c2f1dfa",
"bad4dcf11e584ecf34de291a5295d7c1e2fca4d9"
],
"target": "0e5a56f25f51d07290613a9363bd8c0c9fc8e0be",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "4999dcd5a014a245734b6057bafb9a48f172eaec",
"author": {
"id": "did:key:z6MktwkohCx8aHZ1QCjVZUiLmX92oPZFxRiFZkbq32Tk5Tkm",
"alias": "2color"
},
"description": "This is required for compatiblity with Rust.\n\n\ntreewide: Remove `test_` prefix from test `fn`s\n\nThis redundancy does not add much. These functions are already marked\nvia `#[test]`, and often times they are in a separate module named\n\"test\" or \"tests\".\n\n\nprotocol: Limit allocations when decoding frames\n\n`VarInt` can get large enough to exhaust available memory on many\nmachines. Instead of allocating directly, check the size of the\nallocation against some limit.\n\nThe limit chosen for frames is 128 KiB, which is roughly twice as much\nas actual gossip and Git protocol frames are expected to be. However,\n128 KiB is arguably short enough to not burden a standard consumer\nmachine too much.\n\n\npatch: Use cref rule quorum for merge tally\n\nTo determine whether a patch has been merged to the default branch, we\ntally merges based on the default branch quorum: allow set and\nthreshold. With the introduction of custom branch, the tallying wasn't\nupdated to use the quorum rules for the target branch, instead merging\non the identity document threshold and delegate set.\n\nThis fix uses the `allow` set and the `threshold` of the most specific\nrule that matches the target branch of patch.\n\nNote that a reference that no rule matches never becomes canonical, so a\npatch that targets one can never reach a quorum.\n\n\nradicle: identity 2 and default branch with crefs\n\nThe default branch was the one canonical reference the\n`xyz.radicle.crefs` payload was not allowed to govern. Its name lived in\nthe `defaultBranch` field of the `xyz.radicle.project` payload and its\nquorum in the identity document's top-level `threshold`, from which the\nrule and the `HEAD` symbolic reference were synthesized as\n`Allowed::Delegates` at that threshold. A document that stated either\nitself was rejected: `update::verify` refused a crefs payload defining\n`HEAD`, or any rule matching `defaultBranch`. So the default branch alone\ncould not be governed by a narrower set, unlike every other canonical\nbranch.\n\nCounting votes followed the document, not the rule. A fetch used the\ndocument `threshold` as the number of delegates it must validate before\nit applies any update, so the rule governing the branch it established\nnever set its own quorum.\n\nMake the `xyz.radicle.crefs` payload the sole authority over the\ncanonical head. The rule whose pattern matches the `HEAD` symbolic\nreference now defines the default branch, its `allow` set and its\nthreshold:\n\n- Remove `defaultBranch` and the top-level `threshold`, and synthesize\n the default-branch rule and its `HEAD` symbolic reference on document\n creation.\n- Take the fetch quorum from the rule matching the canonical head: the\n special-refs anchor counts votes from the rule's `allow` set against\n the rule's threshold, so the counted peers and the number required come\n from one place.\n- Fail closed in verification and in fetch when no rule matches, because\n an unresolvable canonical head leaves the repository unloadable.\n Identity revisions stay on a simple delegate majority.\n- Route callers through the identity document, adding\n `ReadRepository::default_branch_name` and threading the branch from\n `rad::init` to `Doc::initial`.\n- Give `rad id` an in-place threshold update that preserves the rule's\n `allow` set.\n\nBump `IDENTITY_VERSION` to 2, and keep version 1 documents readable so\nexisting repositories survive the upgrade:\n\n- Make `RawDoc` an enum over the version 1 and version 2 stored schemas,\n each with its own serialization, so a version 1 document re-encodes\n byte-for-byte as released clients wrote it. The repository id and every\n signature over the document are therefore unchanged.\n- Hold both forms in `Doc`: the stored form decides identity, signing and\n serialization; the migrated view is what every reader consumes. This\n keeps version conditionals out of reader code.\n- Derive the view with one `Migrate` implementation, which also produces\n the document `rad id migrate` proposes, so the implicit and the\n explicit migration cannot drift apart.\n- Enforce the invariants per version: version 1 requires `threshold`,\n and its migration checks that a crefs payload it already carries agrees\n with `defaultBranch` and that threshold. Version 2 rejects a top-level\n `threshold` when deserializing, and a `defaultBranch` when validating,\n which `Project` would otherwise swallow as an unknown field.\n- Keep an ordinary edit on the stored version, so only an explicit\n migration changes it.\n\nAdd `rad id migrate`, which proposes the migrated document as a revision\nthe delegates vote on, and `rad init --identity-version` for a repository\nthat must stay readable to older releases. Adopting the migration is\nopt-in per repository, because it is a one-way door: version 2 is\nunreadable to releases 1.10.0 and earlier.\n\nSign the stored blob in `Revision::sign` rather than a re-encoding of the\nin-memory document. Verification already checks the signature against the\nstored blob, so any disagreement between the two silently broke votes.\n\nBox the success side of `FetchResult::Initiator`. It carries a `DocAt`,\nwhich grows with the stored-plus-view `Doc` from 168 to 264 bytes, so\n`clippy` flags the size difference between the variants.\n\nUpdate the tests, CLI examples and fixtures: repository and derived\ncollaborative-object ids change with the new identity root, dumps carry\nthe `xyz.radicle.crefs` payload and `\"version\": 2`, and the cases that\nraised a document-level threshold are dropped since that knob moved into\nthe crefs payload.\n\nCo-authored-by: Yorgos Saslis <yorgos.work@proton.me>\n\n\nradicle/identity: failing tests for branch-free docs\n\n- Assert a version-2 document with no `xyz.radicle.crefs` payload, and one\n with no payloads at all, are valid and simply cannot name a default branch.\n- Assert a version-1 document with neither `defaultBranch` nor a crefs\n `HEAD` stays readable and migrates.\n- Guard the relaxation: a `HEAD` that no rule governs stays invalid.\n\nIdentity 2 made a resolvable `HEAD` a validity condition of every document,\nwhich is stricter than upstream, where validity never depended on a default\nbranch. These tests pin the intended behaviour before the fix.\n\n\nradicle/identity: make canonical refs optional\n\n- Treat an absent `xyz.radicle.crefs` payload as an empty set instead of an\n error, so a repository may have no canonical references.\n- Validate rather than require crefs in `RawDoc::verified`: a payload that is\n present must resolve, but none need be present.\n- Migrate a version-1 document with no default branch instead of failing. Its\n top-level `threshold` has nowhere to go and governed nothing that survives:\n identity revisions are adopted by `Doc::majority`.\n- Add `Doc::special_refs_quorum`, which reads the voters and threshold from\n the rule governing the default branch, and falls back to the delegates and\n their majority when there is none.\n- Fall back the same way in `update::verify_delegates`, and read the branch\n from the proposal rather than the repository, since that is the document\n the delegates must serve once it is adopted.\n\nIdentity 2 made a resolvable `HEAD` a validity condition of every document.\nThat is stricter than upstream, where validity never depended on a default\nbranch, and it blocks repositories that hold no branches at all.\n\n\nfetch: fall back to delegate majority with no branch\n\n- Read the special-refs voters and threshold through\n `Doc::special_refs_quorum`, which uses the default branch rule where there\n is one and the delegates' majority where there is not.\n\nA repository with no default branch has no rule to derive the quorum from,\nso the fetch aborted. The precondition is about which peers' `rad/sigrefs`\nmust be present, which does not need a branch to be meaningful.\n\n\nradicle/identity: report a threshold with no branch to set it on\n\n- Make `set_threshold` fallible and return `NoDefaultBranch` when the\n document names none, through `RawDoc`, `update::threshold` and `rad id`.\n\nVersion 2 keeps the write quorum in the crefs rule governing `HEAD`. With no\n`HEAD` there is no rule, and `rad id --threshold` was a no-op but still reported success.\n\n\nradicle: allow initializing without a default branch\n\n- Take `Option` for the default branch in `RawDoc::new`, `Doc::initial` and\n `rad::init`, and their `_at` variants.\n- Write no crefs payload, push no branch, and compute no canonical head when\n there is none. The identity is still published, so the repository exists\n and can gain branches later.\n\nCompletes the path: a repository that holds no branches can now be created,\nnot only parsed.\n\nNote that `rad init` still always names a branch. Exposing this on the command\nline is a separate decision.\n\n\nradicle/identity: say what a missing default branch means\n\n- Reword `DefaultBranchError::MissingHead` to name the document and the\n payload, not the bare symbolic reference.\n\nA branch-free repository now reaches users through this error, for example\nwhen a patch targets the delegates' default branch, so it must explain\nitself rather than report a missing `HEAD`.",
"base": "dc4d5c93963ecb12b66ce850afdc6054c0eec8e5",
"oid": "e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799",
"timestamp": 1789125979
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "96c9545b-f698-4e88-986a-49d537f839ae"
},
"info_url": "https://cci.rad.levitte.org//96c9545b-f698-4e88-986a-49d537f839ae.html"
}
Started at: 2026-09-11 13:26:30.747715+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/96c9545b-f698-4e88-986a-49d537f839ae/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 190 issues · 40 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 4999dcd5a014a245734b6057bafb9a48f172eaec
✓ Switched to branch patch/4999dcd at revision 4999dcd
✓ Branch patch/4999dcd setup to track rad/patches/4999dcd5a014a245734b6057bafb9a48f172eaec
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799
HEAD is now at e1e4a2f3 radicle/identity: say what a missing default branch means
Exit code: 0
$ rad patch show 4999dcd5a014a245734b6057bafb9a48f172eaec -p
╭──────────────────────────────────────────────────────────────────────────────────╮
│ Title build/Dockerfile: Bump `cargo-zigbuild` │
│ Patch 4999dcd5a014a245734b6057bafb9a48f172eaec │
│ Author 2color z6Mktwk…2Tk5Tkm │
│ Head e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799 │
│ Base dc4d5c93963ecb12b66ce850afdc6054c0eec8e5 │
│ Target master │
│ Branches patch/4999dcd │
│ Commits ahead 8, behind 0 │
│ Status open │
│ │
│ This is required for compatiblity with Rust. │
│ │
│ │
│ treewide: Remove `test_` prefix from test `fn`s │
│ │
│ This redundancy does not add much. These functions are already marked │
│ via `#[test]`, and often times they are in a separate module named │
│ "test" or "tests". │
│ │
│ │
│ protocol: Limit allocations when decoding frames │
│ │
│ `VarInt` can get large enough to exhaust available memory on many │
│ machines. Instead of allocating directly, check the size of the │
│ allocation against some limit. │
│ │
│ The limit chosen for frames is 128 KiB, which is roughly twice as much │
│ as actual gossip and Git protocol frames are expected to be. However, │
│ 128 KiB is arguably short enough to not burden a standard consumer │
│ machine too much. │
│ │
│ │
│ patch: Use cref rule quorum for merge tally │
│ │
│ To determine whether a patch has been merged to the default branch, we │
│ tally merges based on the default branch quorum: allow set and │
│ threshold. With the introduction of custom branch, the tallying wasn't │
│ updated to use the quorum rules for the target branch, instead merging │
│ on the identity document threshold and delegate set. │
│ │
│ This fix uses the `allow` set and the `threshold` of the most specific │
│ rule that matches the target branch of patch. │
│ │
│ Note that a reference that no rule matches never becomes canonical, so a │
│ patch that targets one can never reach a quorum. │
│ │
│ │
│ radicle: identity 2 and default branch with crefs │
│ │
│ The default branch was the one canonical reference the │
│ `xyz.radicle.crefs` payload was not allowed to govern. Its name lived in │
│ the `defaultBranch` field of the `xyz.radicle.project` payload and its │
│ quorum in the identity document's top-level `threshold`, from which the │
│ rule and the `HEAD` symbolic reference were synthesized as │
│ `Allowed::Delegates` at that threshold. A document that stated either │
│ itself was rejected: `update::verify` refused a crefs payload defining │
│ `HEAD`, or any rule matching `defaultBranch`. So the default branch alone │
│ could not be governed by a narrower set, unlike every other canonical │
│ branch. │
│ │
│ Counting votes followed the document, not the rule. A fetch used the │
│ document `threshold` as the number of delegates it must validate before │
│ it applies any update, so the rule governing the branch it established │
│ never set its own quorum. │
│ │
│ Make the `xyz.radicle.crefs` payload the sole authority over the │
│ canonical head. The rule whose pattern matches the `HEAD` symbolic │
│ reference now defines the default branch, its `allow` set and its │
│ threshold: │
│ │
│ - Remove `defaultBranch` and the top-level `threshold`, and synthesize │
│ the default-branch rule and its `HEAD` symbolic reference on document │
│ creation. │
│ - Take the fetch quorum from the rule matching the canonical head: the │
│ special-refs anchor counts votes from the rule's `allow` set against │
│ the rule's threshold, so the counted peers and the number required come │
│ from one place. │
│ - Fail closed in verification and in fetch when no rule matches, because │
│ an unresolvable canonical head leaves the repository unloadable. │
│ Identity revisions stay on a simple delegate majority. │
│ - Route callers through the identity document, adding │
│ `ReadRepository::default_branch_name` and threading the branch from │
│ `rad::init` to `Doc::initial`. │
│ - Give `rad id` an in-place threshold update that preserves the rule's │
│ `allow` set. │
│ │
│ Bump `IDENTITY_VERSION` to 2, and keep version 1 documents readable so │
│ existing repositories survive the upgrade: │
│ │
│ - Make `RawDoc` an enum over the version 1 and version 2 stored schemas, │
│ each with its own serialization, so a version 1 document re-encodes │
│ byte-for-byte as released clients wrote it. The repository id and every │
│ signature over the document are therefore unchanged. │
│ - Hold both forms in `Doc`: the stored form decides identity, signing and │
│ serialization; the migrated view is what every reader consumes. This │
│ keeps version conditionals out of reader code. │
│ - Derive the view with one `Migrate` implementation, which also produces │
│ the document `rad id migrate` proposes, so the implicit and the │
│ explicit migration cannot drift apart. │
│ - Enforce the invariants per version: version 1 requires `threshold`, │
│ and its migration checks that a crefs payload it already carries agrees │
│ with `defaultBranch` and that threshold. Version 2 rejects a top-level │
│ `threshold` when deserializing, and a `defaultBranch` when validating, │
│ which `Project` would otherwise swallow as an unknown field. │
│ - Keep an ordinary edit on the stored version, so only an explicit │
│ migration changes it. │
│ │
│ Add `rad id migrate`, which proposes the migrated document as a revision │
│ the delegates vote on, and `rad init --identity-version` for a repository │
│ that must stay readable to older releases. Adopting the migration is │
│ opt-in per repository, because it is a one-way door: version 2 is │
│ unreadable to releases 1.10.0 and earlier. │
│ │
│ Sign the stored blob in `Revision::sign` rather than a re-encoding of the │
│ in-memory document. Verification already checks the signature against the │
│ stored blob, so any disagreement between the two silently broke votes. │
│ │
│ Box the success side of `FetchResult::Initiator`. It carries a `DocAt`, │
│ which grows with the stored-plus-view `Doc` from 168 to 264 bytes, so │
│ `clippy` flags the size difference between the variants. │
│ │
│ Update the tests, CLI examples and fixtures: repository and derived │
│ collaborative-object ids change with the new identity root, dumps carry │
│ the `xyz.radicle.crefs` payload and `"version": 2`, and the cases that │
│ raised a document-level threshold are dropped since that knob moved into │
│ the crefs payload. │
│ │
│ Co-authored-by: Yorgos Saslis <yorgos.work@proton.me> │
│ │
│ │
│ radicle/identity: failing tests for branch-free docs │
│ │
│ - Assert a version-2 document with no `xyz.radicle.crefs` payload, and one │
│ with no payloads at all, are valid and simply cannot name a default branch. │
│ - Assert a version-1 document with neither `defaultBranch` nor a crefs │
│ `HEAD` stays readable and migrates. │
│ - Guard the relaxation: a `HEAD` that no rule governs stays invalid. │
│ │
│ Identity 2 made a resolvable `HEAD` a validity condition of every document, │
│ which is stricter than upstream, where validity never depended on a default │
│ branch. These tests pin the intended behaviour before the fix. │
│ │
│ │
│ radicle/identity: make canonical refs optional │
│ │
│ - Treat an absent `xyz.radicle.crefs` payload as an empty set instead of an │
│ error, so a repository may have no canonical references. │
│ - Validate rather than require crefs in `RawDoc::verified`: a payload that is │
│ present must resolve, but none need be present. │
│ - Migrate a version-1 document with no default branch instead of failing. Its │
│ top-level `threshold` has nowhere to go and governed nothing that survives: │
│ identity revisions are adopted by `Doc::majority`. │
│ - Add `Doc::special_refs_quorum`, which reads the voters and threshold from │
│ the rule governing the default branch, and falls back to the delegates and │
│ their majority when there is none. │
│ - Fall back the same way in `update::verify_delegates`, and read the branch │
│ from the proposal rather than the repository, since that is the document │
│ the delegates must serve once it is adopted. │
│ │
│ Identity 2 made a resolvable `HEAD` a validity condition of every document. │
│ That is stricter than upstream, where validity never depended on a default │
│ branch, and it blocks repositories that hold no branches at all. │
│ │
│ │
│ fetch: fall back to delegate majority with no branch │
│ │
│ - Read the special-refs voters and threshold through │
│ `Doc::special_refs_quorum`, which uses the default branch rule where there │
│ is one and the delegates' majority where there is not. │
│ │
│ A repository with no default branch has no rule to derive the quorum from, │
│ so the fetch aborted. The precondition is about which peers' `rad/sigrefs` │
│ must be present, which does not need a branch to be meaningful. │
│ │
│ │
│ radicle/identity: report a threshold with no branch to set it on │
│ │
│ - Make `set_threshold` fallible and return `NoDefaultBranch` when the │
│ document names none, through `RawDoc`, `update::threshold` and `rad id`. │
│ │
│ Version 2 keeps the write quorum in the crefs rule governing `HEAD`. With no │
│ `HEAD` there is no rule, and `rad id --threshold` was a no-op but still reported │
│ success. │
│ │
│ │
│ radicle: allow initializing without a default branch │
│ │
│ - Take `Option` for the default branch in `RawDoc::new`, `Doc::initial` and │
│ `rad::init`, and their `_at` variants. │
│ - Write no crefs payload, push no branch, and compute no canonical head when │
│ there is none. The identity is still published, so the repository exists │
│ and can gain branches later. │
│ │
│ Completes the path: a repository that holds no branches can now be created, │
│ not only parsed. │
│ │
│ Note that `rad init` still always names a branch. Exposing this on the command │
│ line is a separate decision. │
│ │
│ │
│ radicle/identity: say what a missing default branch means │
│ │
│ - Reword `DefaultBranchError::MissingHead` to name the document and the │
│ payload, not the bare symbolic reference. │
│ │
│ A branch-free repository now reaches users through this error, for example │
│ when a patch targets the delegates' default branch, so it must explain │
│ itself rather than report a missing `HEAD`. │
├──────────────────────────────────────────────────────────────────────────────────┤
│ e1e4a2f radicle/identity: say what a missing default branch means │
│ 29e0323 radicle: allow initializing without a default branch │
│ 02be3e8 radicle/identity: report a threshold with no branch to set it on │
│ b887cc9 fetch: fall back to delegate majority with no branch │
│ 7e62c62 radicle/identity: make canonical refs optional │
│ ed86a2b radicle/identity: failing tests for branch-free docs │
│ 71694a2 radicle: identity 2 and default branch with crefs │
│ 7a77ba4 patch: Use cref rule quorum for merge tally │
│ 0e5a56f protocol: Limit allocations when decoding frames │
│ d8298a1 treewide: Remove `test_` prefix from test `fn`s │
│ 7e1cb40 build/Dockerfile: Bump `cargo-zigbuild` │
├──────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision 4999dcd @ dc4d5c9..e1e4a2f by 2color z6Mktwk…2Tk5Tkm 13 seconds ago │
╰──────────────────────────────────────────────────────────────────────────────────╯
commit e1e4a2f302cfe5c0b1fe6c9928bc9331d9cf2799
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 12:01:54 2026 +0200
radicle/identity: say what a missing default branch means
- Reword `DefaultBranchError::MissingHead` to name the document and the
payload, not the bare symbolic reference.
A branch-free repository now reaches users through this error, for example
when a patch targets the delegates' default branch, so it must explain
itself rather than report a missing `HEAD`.
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index 455095b1fa..e9110c7fbb 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -99,7 +99,10 @@ impl DocError {
#[derive(Debug, Error)]
pub enum DefaultBranchError {
- #[error("no symbolic reference with name `HEAD` is defined")]
+ #[error(
+ "the identity document names no default branch: the `xyz.radicle.crefs` payload \
+ defines no `HEAD` symbolic reference"
+ )]
MissingHead,
#[error(transparent)]
commit 29e032302531e7ba9e7de33733e1d6e3eb114003
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 11:57:21 2026 +0200
radicle: allow initializing without a default branch
- Take `Option` for the default branch in `RawDoc::new`, `Doc::initial` and
`rad::init`, and their `_at` variants.
- Write no crefs payload, push no branch, and compute no canonical head when
there is none. The identity is still published, so the repository exists
and can gain branches later.
Completes the path: a repository that holds no branches can now be created,
not only parsed.
Note that `rad init` still always names a branch. Exposing this on the command
line is a separate decision.
diff --git a/crates/radicle-cli/src/commands/init.rs b/crates/radicle-cli/src/commands/init.rs
index 7087086ec4..457b226af0 100644
--- a/crates/radicle-cli/src/commands/init.rs
+++ b/crates/radicle-cli/src/commands/init.rs
@@ -142,7 +142,7 @@ pub fn init(repo: raw::Repository, args: Args, profile: &profile::Profile) -> an
&repo,
name,
&description,
- branch.clone(),
+ Some(branch.clone()),
visibility,
&signer,
&profile.storage,
diff --git a/crates/radicle-node/src/test/node.rs b/crates/radicle-node/src/test/node.rs
index b427c4faeb..ab89340b1a 100644
--- a/crates/radicle-node/src/test/node.rs
+++ b/crates/radicle-node/src/test/node.rs
@@ -515,7 +515,7 @@ impl Node {
repo,
name.try_into().unwrap(),
description,
- branch.clone(),
+ Some(branch.clone()),
Visibility::default(),
&self.secret_key,
&self.storage,
diff --git a/crates/radicle-node/src/test/peer.rs b/crates/radicle-node/src/test/peer.rs
index 779ad4ab0e..0ea5ffd5bd 100644
--- a/crates/radicle-node/src/test/peer.rs
+++ b/crates/radicle-node/src/test/peer.rs
@@ -145,7 +145,7 @@ impl Peer<Storage> {
&repo,
name.try_into().unwrap(),
description,
- radicle::git::fmt::refname!("master"),
+ Some(radicle::git::fmt::refname!("master")),
Visibility::default(),
self.secret_key(),
self.storage(),
diff --git a/crates/radicle-node/src/tests.rs b/crates/radicle-node/src/tests.rs
index 46944d37c7..0c9974183e 100644
--- a/crates/radicle-node/src/tests.rs
+++ b/crates/radicle-node/src/tests.rs
@@ -1820,7 +1820,7 @@ fn init_and_seed() {
&repo,
"amy".try_into().unwrap(),
"amy's repo",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
amy.secret_key(),
amy.storage(),
diff --git a/crates/radicle/src/cob/identity.rs b/crates/radicle/src/cob/identity.rs
index 3b695d312f..36890a48e6 100644
--- a/crates/radicle/src/cob/identity.rs
+++ b/crates/radicle/src/cob/identity.rs
@@ -1421,7 +1421,7 @@ mod test {
&working,
"heartwood".try_into().unwrap(),
"Radicle Heartwood Protocol & Stack",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&alice,
&storage,
diff --git a/crates/radicle/src/cob/patch.rs b/crates/radicle/src/cob/patch.rs
index 2c3eaf0c3a..9e1b990af0 100644
--- a/crates/radicle/src/cob/patch.rs
+++ b/crates/radicle/src/cob/patch.rs
@@ -3142,7 +3142,7 @@ mod test {
let doc = RawDoc::new(
project.unwrap(),
vec![alice.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
)
@@ -3195,7 +3195,7 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
);
@@ -3279,7 +3279,7 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![bob.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
);
@@ -3339,7 +3339,7 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
);
@@ -3407,7 +3407,7 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did(), bob.did(), eve.did(), dave.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
3,
identity::Visibility::Public,
);
@@ -3551,7 +3551,7 @@ mod test {
let doc = RawDoc::new(
project,
vec![alice.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
)
@@ -3614,7 +3614,7 @@ mod test {
let doc = RawDoc::new(
project,
vec![alice.did(), bob.did(), eve.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
2,
identity::Visibility::Public,
)
@@ -3909,7 +3909,7 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
identity::Visibility::Public,
)
diff --git a/crates/radicle/src/git/canonical/rules/test.rs b/crates/radicle/src/git/canonical/rules/test.rs
index 51550ba869..77f9321ad5 100644
--- a/crates/radicle/src/git/canonical/rules/test.rs
+++ b/crates/radicle/src/git/canonical/rules/test.rs
@@ -365,7 +365,7 @@ fn canonical() {
&repo,
"heartwood".try_into().unwrap(),
"Radicle Heartwood Protocol & Stack",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&delegate,
&storage,
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index 39bd464a84..455095b1fa 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -651,10 +651,13 @@ impl Doc {
/// It will begin with the provided `project` in the [`Doc::payload`], a
/// `xyz.radicle.crefs` payload governing `default_branch` with a threshold
/// of 1, the `delegate` as the sole delegate, and the given `visibility`.
+ ///
+ /// The default branch is optional: a repository that holds no branches
+ /// gets no canonical references, and so no crefs payload.
pub fn initial(
project: Project,
delegate: Did,
- default_branch: &RefString,
+ default_branch: Option<&RefString>,
visibility: Visibility,
) -> Self {
Self::initial_at(
@@ -676,7 +679,7 @@ impl Doc {
version: Version,
project: Project,
delegate: Did,
- default_branch: &RefString,
+ default_branch: Option<&RefString>,
visibility: Visibility,
) -> Result<Self, DocError> {
RawDoc::new_at(
@@ -992,7 +995,7 @@ mod test {
let mut doc = RawDoc::new(
r#gen::<Project>(1),
vec![did],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
Visibility::Public,
);
@@ -1013,7 +1016,7 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
delegates[0..MAX_DELEGATES].into(),
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
Visibility::Public,
);
@@ -1023,7 +1026,7 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
delegates,
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
Visibility::Public,
);
@@ -1042,7 +1045,7 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
vec![did],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
2,
Visibility::Public,
);
@@ -1057,7 +1060,7 @@ mod test {
let mut doc = RawDoc::new(
r#gen::<Project>(1),
vec![r#gen::<Did>(1)],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
Visibility::Public,
);
@@ -1351,7 +1354,7 @@ mod test {
&repo,
"heartwood".try_into().unwrap(),
"Radicle Heartwood Protocol & Stack",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&delegate,
&storage,
@@ -1401,7 +1404,7 @@ mod test {
&working,
"heartwood".try_into().unwrap(),
"Radicle Heartwood Protocol & Stack",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&delegate,
&storage,
diff --git a/crates/radicle/src/identity/doc/raw.rs b/crates/radicle/src/identity/doc/raw.rs
index 192efc7329..d110c389e2 100644
--- a/crates/radicle/src/identity/doc/raw.rs
+++ b/crates/radicle/src/identity/doc/raw.rs
@@ -93,11 +93,14 @@ impl RawDoc {
/// payload governing `default_branch` at the given `threshold`, with the
/// given `delegates` and `visibility`.
///
+ /// The default branch is optional: a repository that holds no branches
+ /// gets no canonical references, and so no crefs payload.
+ ///
/// [`IDENTITY_VERSION`]: super::IDENTITY_VERSION
pub fn new(
project: Project,
delegates: Vec<Did>,
- default_branch: &RefString,
+ default_branch: Option<&RefString>,
threshold: usize,
visibility: Visibility,
) -> Self {
@@ -119,7 +122,7 @@ impl RawDoc {
version: Version,
project: Project,
delegates: Vec<Did>,
- default_branch: &RefString,
+ default_branch: Option<&RefString>,
threshold: usize,
visibility: Visibility,
) -> Self {
@@ -129,7 +132,9 @@ impl RawDoc {
match u32::from(version) {
1 => {
let mut project = project;
- if let Some(object) = project.as_object_mut() {
+ if let Some(default_branch) = default_branch
+ && let Some(object) = project.as_object_mut()
+ {
object.insert(
"defaultBranch".to_owned(),
json::Value::from(default_branch.as_str()),
@@ -145,17 +150,21 @@ impl RawDoc {
visibility,
})
}
- _ => Self::V2(v2::Doc {
- payload: BTreeMap::from_iter([
- (PayloadId::project().clone(), Payload::from(project)),
- (
+ _ => {
+ let mut payload =
+ BTreeMap::from_iter([(PayloadId::project().clone(), Payload::from(project))]);
+ if let Some(default_branch) = default_branch {
+ payload.insert(
PayloadId::canonical_refs().clone(),
v2::default_branch_crefs(default_branch, threshold),
- ),
- ]),
- delegates,
- visibility,
- }),
+ );
+ }
+ Self::V2(v2::Doc {
+ payload,
+ delegates,
+ visibility,
+ })
+ }
}
}
diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs
index 98360800c6..e79b4a4c77 100644
--- a/crates/radicle/src/rad.rs
+++ b/crates/radicle/src/rad.rs
@@ -46,11 +46,14 @@ pub enum InitError {
/// Initialize a new Radicle project from a git repository, at the current
/// identity document version.
+///
+/// The default branch is optional: a repository that holds no branches gets
+/// no canonical references, and so no `xyz.radicle.crefs` payload.
pub fn init(
repo: &git::raw::Repository,
name: ProjectName,
description: &str,
- default_branch: BranchName,
+ default_branch: Option<BranchName>,
visibility: Visibility,
signer: &impl crypto::Signer,
storage: &impl WriteStorage,
@@ -77,7 +80,7 @@ pub fn init_at(
repo: &git::raw::Repository,
name: ProjectName,
description: &str,
- default_branch: BranchName,
+ default_branch: Option<BranchName>,
visibility: Visibility,
signer: &impl crypto::Signer,
storage: &impl WriteStorage,
@@ -92,12 +95,20 @@ pub fn init_at(
.join(", "),
)
})?;
- let doc = identity::Doc::initial_at(version, proj, delegate, &default_branch, visibility)?;
+ let doc =
+ identity::Doc::initial_at(version, proj, delegate, default_branch.as_ref(), visibility)?;
let (project, identity) = Repository::init(&doc, storage, signer)?;
let url = git::Url::from(project.id);
- match init_configure(repo, &project, &default_branch, &url, identity, signer) {
+ match init_configure(
+ repo,
+ &project,
+ default_branch.as_ref(),
+ &url,
+ identity,
+ signer,
+ ) {
Ok(signed) => Ok((project.id, doc, signed)),
Err(err) => {
if let Err(e) = project.remove() {
@@ -116,7 +127,7 @@ pub fn init_at(
fn init_configure(
repo: &git::raw::Repository,
stored: &Repository,
- default_branch: &BranchName,
+ default_branch: Option<&BranchName>,
url: &git::Url,
identity: git::Oid,
signer: &impl crypto::Signer,
@@ -125,40 +136,49 @@ fn init_configure(
git::configure_repository(repo)?;
git::configure_remote(repo, &REMOTE_NAME, url, &url.clone().with_namespace(*pk))?;
- let branch = git::fmt::Qualified::from(git::fmt::lit::refs_heads(default_branch));
- {
- // Push branch to storage.
- let stored = dunce::canonicalize(stored.path())?.display().to_string();
+ // With no default branch there is nothing to push, no remote branch to
+ // track, and no canonical head to compute. The identity itself is still
+ // published, so the repository exists and can gain branches later.
+ if let Some(default_branch) = default_branch {
+ let branch = git::fmt::Qualified::from(git::fmt::lit::refs_heads(default_branch));
+
+ {
+ // Push branch to storage.
+ let stored = dunce::canonicalize(stored.path())?.display().to_string();
+
+ // Pushes to default branch to the namespace of the `signer`.
+ let pushspec = git::fmt::refspec::Refspec {
+ src: branch.clone(),
+ dst: branch.clone().with_namespace(git::fmt::Component::from(pk)),
+ force: false,
+ }
+ .to_string();
- // Pushes to default branch to the namespace of the `signer`.
- let pushspec = git::fmt::refspec::Refspec {
- src: branch.clone(),
- dst: branch.with_namespace(git::fmt::Component::from(pk)),
- force: false,
+ git::run(Some(repo.path()), ["push".to_string(), stored, pushspec])?;
}
- .to_string();
- git::run(Some(repo.path()), ["push".to_string(), stored, pushspec])?;
+ // N.b. we need to create the remote branch for the default branch
+ let rad_remote = git::fmt::Qualified::from(git::fmt::lit::refs_remotes(&*REMOTE_COMPONENT))
+ .join(default_branch);
+ let oid = repo.refname_to_id(branch.as_str())?;
+ repo.reference(
+ rad_remote.as_str(),
+ oid,
+ false,
+ &format!(
+ "radicle: remote branch {}/{}",
+ *REMOTE_COMPONENT, default_branch
+ ),
+ )?;
}
- // N.b. we need to create the remote branch for the default branch
- let rad_remote = git::fmt::Qualified::from(git::fmt::lit::refs_remotes(&*REMOTE_COMPONENT))
- .join(default_branch);
- let oid = repo.refname_to_id(branch.as_str())?;
- repo.reference(
- rad_remote.as_str(),
- oid,
- false,
- &format!(
- "radicle: remote branch {}/{}",
- *REMOTE_COMPONENT, default_branch
- ),
- )?;
stored.set_remote_identity_root_to(pk, identity)?;
stored.set_identity_head_to(identity)?;
stored.set_canonical_symbolic_refs("set-canonical from init (radicle)")?;
- stored.set_default_branch_to_canonical_head()?;
+ if default_branch.is_some() {
+ stored.set_default_branch_to_canonical_head()?;
+ }
let signed = stored.sign_refs(signer)?;
@@ -524,6 +544,7 @@ mod tests {
use pretty_assertions::assert_eq;
+ use crate::assert_matches;
use crate::crypto::{Signer as _, SigningKey};
use crate::identity::Did;
use crate::storage::git::Storage;
@@ -548,7 +569,7 @@ mod tests {
&repo,
"acme".try_into().unwrap(),
"Acme's repo",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&signer,
&storage,
@@ -586,6 +607,48 @@ mod tests {
assert_eq!(doc.delegates().first(), &Did::from(public_key));
}
+ /// A repository may hold no branches. Initializing without a default
+ /// branch publishes the identity and nothing else: no canonical
+ /// references, no pushed branch, no canonical head.
+ #[test]
+ fn test_init_without_default_branch() {
+ let tempdir = tempfile::tempdir().unwrap();
+ let signer = SigningKey::mock(74);
+ let public_key = signer.public_key();
+ let storage = Storage::open(tempdir.path().join("storage"), fixtures::user()).unwrap();
+
+ transport::local::register(storage.clone());
+
+ let (repo, _) = fixtures::repository(tempdir.path().join("working"));
+ let (rid, doc, _) = init(
+ &repo,
+ "acme".try_into().unwrap(),
+ "Acme's repo",
+ None,
+ Visibility::default(),
+ &signer,
+ &storage,
+ )
+ .unwrap();
+
+ assert!(
+ doc.payload()
+ .get(identity::doc::PayloadId::canonical_refs())
+ .is_none()
+ );
+ assert_matches!(
+ doc.default_branch(),
+ Err(identity::doc::DefaultBranchError::MissingHead)
+ );
+ assert_eq!(doc.delegates().first(), &Did::from(public_key));
+
+ // The identity is readable from storage, and the repository has no
+ // canonical head to compute.
+ let stored = storage.get(rid).unwrap().unwrap();
+ assert_eq!(stored, doc);
+ assert!(storage.repository(rid).unwrap().canonical_head().is_err());
+ }
+
#[test]
fn fork() {
let mut rng = fastrand::Rng::new();
@@ -603,7 +666,7 @@ mod tests {
&original,
"acme".try_into().unwrap(),
"Acme's repo",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&alice,
&storage,
@@ -639,7 +702,7 @@ mod tests {
&original,
"acme".try_into().unwrap(),
"Acme's repo",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
&signer,
&storage,
diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs
index 6029f4aec5..f9eeeb0967 100644
--- a/crates/radicle/src/storage/refs.rs
+++ b/crates/radicle/src/storage/refs.rs
@@ -533,7 +533,7 @@ mod tests {
&paris_repo,
"paris".try_into().unwrap(),
"Paris repository",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Default::default(),
&alice,
storage,
@@ -546,7 +546,7 @@ mod tests {
&london_repo,
"london".try_into().unwrap(),
"London repository",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Default::default(),
&alice,
storage,
diff --git a/crates/radicle/src/test/arbitrary.rs b/crates/radicle/src/test/arbitrary.rs
index 9357cb814c..98f3bdbb72 100644
--- a/crates/radicle/src/test/arbitrary.rs
+++ b/crates/radicle/src/test/arbitrary.rs
@@ -174,7 +174,7 @@ pub fn raw_doc_at(version: Version) -> RawDoc {
version,
r#gen::<Project>(1),
vec![r#gen::<Did>(1)],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
Visibility::Public,
)
@@ -190,7 +190,7 @@ impl Arbitrary for RawDoc {
identity_version(g),
proj,
vec![delegate],
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
1,
visibility,
)
@@ -207,7 +207,7 @@ impl Arbitrary for Doc {
identity_version(g),
project,
delegates,
- &git::fmt::refname!("master"),
+ Some(&git::fmt::refname!("master")),
threshold,
visibility,
);
diff --git a/crates/radicle/src/test/fixtures.rs b/crates/radicle/src/test/fixtures.rs
index c2578c5f36..5ddf0f5c68 100644
--- a/crates/radicle/src/test/fixtures.rs
+++ b/crates/radicle/src/test/fixtures.rs
@@ -58,7 +58,7 @@ pub fn storage(
&repo,
name.try_into().unwrap(),
desc,
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
signer,
&storage,
@@ -81,7 +81,7 @@ pub fn project(
&working,
"acme".try_into().unwrap(),
"Acme's repository",
- git::fmt::refname!("master"),
+ Some(git::fmt::refname!("master")),
Visibility::default(),
signer,
storage,
commit 02be3e8e2cdbd049fe88cb6415f4b8ce70fe65e1
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 11:54:38 2026 +0200
radicle/identity: report a threshold with no branch to set it on
- Make `set_threshold` fallible and return `NoDefaultBranch` when the
document names none, through `RawDoc`, `update::threshold` and `rad id`.
Version 2 keeps the write quorum in the crefs rule governing `HEAD`. With no
`HEAD` there is no rule, and `rad id --threshold` was a no-op but still reported success.
diff --git a/crates/radicle-cli/src/commands/id.rs b/crates/radicle-cli/src/commands/id.rs
index 64b8c45259..5f01df37b7 100644
--- a/crates/radicle-cli/src/commands/id.rs
+++ b/crates/radicle-cli/src/commands/id.rs
@@ -121,7 +121,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
let disallow = disallow.into_iter().collect::<BTreeSet<_>>();
let proposal = match threshold {
- Some(threshold) => update::threshold(proposal, threshold),
+ Some(threshold) => update::threshold(proposal, threshold)?,
None => proposal,
};
diff --git a/crates/radicle/src/identity/doc/raw.rs b/crates/radicle/src/identity/doc/raw.rs
index fa24060982..192efc7329 100644
--- a/crates/radicle/src/identity/doc/raw.rs
+++ b/crates/radicle/src/identity/doc/raw.rs
@@ -206,9 +206,18 @@ impl RawDoc {
/// Where the threshold is stored depends on the version: version 1 has a
/// top-level field, while version 2 keeps it in the `xyz.radicle.crefs`
/// rule governing `HEAD`.
- pub fn set_threshold(&mut self, threshold: usize) {
+ ///
+ /// # Errors
+ ///
+ /// A version-2 document that names no default branch has no rule to hold
+ /// the quorum. Version 1 always has the top-level field, so it cannot
+ /// fail.
+ pub fn set_threshold(&mut self, threshold: usize) -> Result<(), v2::NoDefaultBranch> {
match self {
- Self::V1(doc) => doc.threshold = threshold,
+ Self::V1(doc) => {
+ doc.threshold = threshold;
+ Ok(())
+ }
Self::V2(doc) => doc.set_threshold(threshold),
}
}
diff --git a/crates/radicle/src/identity/doc/update.rs b/crates/radicle/src/identity/doc/update.rs
index dc16c0474f..882acc2cc4 100644
--- a/crates/radicle/src/identity/doc/update.rs
+++ b/crates/radicle/src/identity/doc/update.rs
@@ -58,9 +58,14 @@ pub fn visibility(mut raw: RawDoc, edit: EditVisibility) -> RawDoc {
///
/// Where the threshold is stored depends on the document version, which
/// [`RawDoc::set_threshold`] takes care of.
-pub fn threshold(mut raw: RawDoc, threshold: usize) -> RawDoc {
- raw.set_threshold(threshold);
- raw
+///
+/// # Errors
+///
+/// This fails when the document names no default branch, since the quorum
+/// lives in the canonical reference rule that governs it.
+pub fn threshold(mut raw: RawDoc, threshold: usize) -> Result<RawDoc, super::v2::NoDefaultBranch> {
+ raw.set_threshold(threshold)?;
+ Ok(raw)
}
/// Change the `allow` set of a document if the visibility is set to
@@ -400,7 +405,7 @@ mod test {
}],
)
.unwrap();
- let raw = super::threshold(raw, 3);
+ let raw = super::threshold(raw, 3).unwrap();
let crefs = raw.raw_canonical_refs().unwrap().unwrap();
let threshold_of = |pattern: &str| {
@@ -422,12 +427,28 @@ mod test {
);
}
+ /// A document with no default branch has no rule to hold a write quorum.
+ /// Setting a threshold must say so, rather than silently doing nothing.
+ #[test]
+ fn test_threshold_without_default_branch_is_rejected() {
+ let raw: crate::prelude::RawDoc = serde_json::from_value(json!({
+ "version": 2,
+ "payload": {},
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
+ ]
+ }))
+ .unwrap();
+
+ assert!(super::threshold(raw, 1).is_err());
+ }
+
#[test]
fn threshold_writes_version_1_field() {
// A version-1 document keeps its quorum in the top-level `threshold`,
// so an ordinary edit must write there and leave the version alone.
let raw = arbitrary::raw_doc_at(Version::new(1).unwrap());
- let raw = super::threshold(raw, 1);
+ let raw = super::threshold(raw, 1).unwrap();
let doc = super::verify(raw).unwrap();
assert_eq!(doc.version(), Version::new(1).unwrap());
diff --git a/crates/radicle/src/identity/doc/v2.rs b/crates/radicle/src/identity/doc/v2.rs
index 6662d627c9..347053ecf2 100644
--- a/crates/radicle/src/identity/doc/v2.rs
+++ b/crates/radicle/src/identity/doc/v2.rs
@@ -72,9 +72,14 @@ impl Doc {
///
/// The threshold lives in the `xyz.radicle.crefs` rule that matches the
/// target of the `HEAD` symbolic reference. This rewrites that rule's
- /// threshold, preserving its `allow` value. If no such rule is present, the
- /// document is left unchanged.
- pub fn set_threshold(&mut self, threshold: usize) {
+ /// threshold, preserving its `allow` value.
+ ///
+ /// # Errors
+ ///
+ /// A document that names no default branch has no rule to hold a quorum,
+ /// so there is nothing to set. Saying so beats writing the threshold
+ /// nowhere and reporting success.
+ pub fn set_threshold(&mut self, threshold: usize) -> Result<(), NoDefaultBranch> {
let mut crefs = self
.raw_canonical_refs()
.and_then(|crefs| crefs.ok())
@@ -83,39 +88,51 @@ impl Doc {
// `RawSymbolicRefs` cannot resolve a `HEAD` chain, so validate them
// first.
let symbolic = SymbolicRefs::try_from(crefs.symbolic().clone()).ok();
- if let Some(head) = symbolic.as_ref().and_then(|symbolic| symbolic.resolve_head()) {
- // Target the *most specific* rule matching `HEAD`, consistent with
- // the enforcement paths (`Doc::canonical_refs`, patch merge,
- // fetch). Because `RawRules` is keyed by plain byte order,
- // `RawRules::matches().next()` could rewrite a broad glob (e.g.
- // `refs/heads/*`) instead of the exact branch rule that actually
- // governs the quorum. Resolving through validated `Rules` restores
- // specificity ordering.
- let pattern = Delegates::new(self.delegates.clone())
- .ok()
- .and_then(|delegates| {
- Rules::from_raw(crefs.raw_rules().clone(), &mut || delegates.clone()).ok()
- })
- .and_then(|rules| rules.matches(head).next().map(|(p, _)| p.clone()));
-
- if let Some(pattern) = pattern
- && let Some(allow) = crefs
- .raw_rules()
- .rules
- .get(&pattern)
- .map(|rule| rule.allowed().clone())
- {
- crefs
- .raw_rules_mut()
- .insert(pattern, rules::Rule::new(allow, threshold));
- }
+ let head = symbolic
+ .as_ref()
+ .and_then(|symbolic| symbolic.resolve_head())
+ .ok_or(NoDefaultBranch)?;
+
+ // Target the *most specific* rule matching `HEAD`, consistent with the
+ // enforcement paths (`Doc::canonical_refs`, patch merge, fetch). Raw
+ // rules cannot be matched against, and validated `Rules` order their
+ // matches by specificity, so a broad glob (e.g. `refs/heads/*`) cannot
+ // shadow the exact branch rule that governs the quorum.
+ let pattern = Delegates::new(self.delegates.clone())
+ .ok()
+ .and_then(|delegates| {
+ Rules::from_raw(crefs.raw_rules().clone(), &mut || delegates.clone()).ok()
+ })
+ .and_then(|rules| rules.matches(head).next().map(|(p, _)| p.clone()));
+
+ if let Some(pattern) = pattern
+ && let Some(allow) = crefs
+ .raw_rules()
+ .rules
+ .get(&pattern)
+ .map(|rule| rule.allowed().clone())
+ {
+ crefs
+ .raw_rules_mut()
+ .insert(pattern, rules::Rule::new(allow, threshold));
}
+
let value = json::to_value(crefs).expect("v2::Doc::set_threshold: crefs are serializable");
self.payload
.insert(PayloadId::canonical_refs().clone(), Payload::from(value));
+
+ Ok(())
}
}
+/// The document names no default branch, so it has no write quorum to set.
+#[derive(Debug, thiserror::Error)]
+#[error(
+ "the identity document names no default branch, so it has no write quorum; \
+ the threshold lives in the `xyz.radicle.crefs` rule governing `HEAD`"
+)]
+pub struct NoDefaultBranch;
+
/// The `xyz.radicle.project` payload of a version-2 document defines
/// `defaultBranch`, which version 2 does not allow.
#[derive(Debug, thiserror::Error)]
commit b887cc99f19533530d794a0381e8eba7f7b55b65
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 11:44:35 2026 +0200
fetch: fall back to delegate majority with no branch
- Read the special-refs voters and threshold through
`Doc::special_refs_quorum`, which uses the default branch rule where there
is one and the delegates' majority where there is not.
A repository with no default branch has no rule to derive the quorum from,
so the fetch aborted. The precondition is about which peers' `rad/sigrefs`
must be present, which does not need a branch to be meaningful.
diff --git a/crates/radicle-fetch/src/state.rs b/crates/radicle-fetch/src/state.rs
index d7b60ef7fb..366edf0651 100644
--- a/crates/radicle-fetch/src/state.rs
+++ b/crates/radicle-fetch/src/state.rs
@@ -419,30 +419,26 @@ impl FetchState {
.canonical()?
.ok_or(error::Protocol::MissingRadId)?;
- // The canonical default branch — and the quorum required to establish
- // it — is defined by the crefs rule that matches it. Fail closed: if the
- // anchor's canonical references or default branch cannot be resolved, or
- // no rule matches, abort the fetch rather than silently proceeding with
- // a quorum of 1 (which would let a single delegate — or a seed serving a
- // malformed 'refs/rad/id' — downgrade the required quorum).
- let crefs = anchor.canonical_refs().map_err(DefaultBranchError::from)?;
- let branch = anchor.default_branch()?;
- let (_, branch_rule) = crefs
- .rules()
- .matches(&branch)
- .next()
+ // The peers who vote on the special references, and how many of them
+ // must answer. Where the anchor names a default branch, both come from
+ // the crefs rule that governs it, so that the threshold and the counted
+ // population agree; where it names none, the delegates and their
+ // majority govern. Fail closed: an unresolvable set of canonical
+ // references, or a declared default branch that no rule governs, aborts
+ // the fetch rather than silently proceeding with a quorum of 1 (which
+ // would let a single delegate — or a seed serving a malformed
+ // 'refs/rad/id' — downgrade the required quorum).
+ let (allowed, branch_threshold) = anchor
+ .special_refs_quorum()
+ .map_err(DefaultBranchError::from)?
.ok_or(error::Protocol::MissingBranchRule)?;
- let branch_threshold = usize::from(*branch_rule.threshold());
- // The peers who vote on the canonical branch are the matched rule's
- // `allowed` set — not the identity delegates — so that the threshold and
- // the counted population come from the same rule. For the common
- // `allow: delegates` rule this set is exactly the identity delegates; for
- // an explicit `allow` set it may include non-delegates.
+ // For the common `allow: delegates` rule the voter set is exactly the
+ // identity delegates; for an explicit `allow` set it may include
+ // non-delegates.
// TODO: not sure we should allow to block *any* peer from the voter set.
// We could end up ignoring voters.
- let voters = branch_rule
- .allowed()
+ let voters = allowed
.iter()
.filter(|id| !handle.is_blocked(id))
.map(|did| PublicKey::from(*did))
@@ -451,12 +447,11 @@ impl FetchState {
log::trace!("Canonical branch voters {voters:?}");
// The local peer does not need to count towards the quorum since they
- // must be valid already. Membership is checked against the rule's full
+ // must be valid already. Membership is checked against the full
// `allowed` set, not the `voters` set above: `voters` has the local peer
// (which is always "blocked" from itself) and any blocked peers filtered
// out, so it must not be used to decide whether the local peer votes.
- let is_voter = branch_rule
- .allowed()
+ let is_voter = allowed
.iter()
.any(|did| PublicKey::from(*did) == *handle.local());
let threshold = if is_voter {
commit 7e62c628f7a3d4a800957cef7d475ef70d0e5aff
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 11:44:35 2026 +0200
radicle/identity: make canonical refs optional
- Treat an absent `xyz.radicle.crefs` payload as an empty set instead of an
error, so a repository may have no canonical references.
- Validate rather than require crefs in `RawDoc::verified`: a payload that is
present must resolve, but none need be present.
- Migrate a version-1 document with no default branch instead of failing. Its
top-level `threshold` has nowhere to go and governed nothing that survives:
identity revisions are adopted by `Doc::majority`.
- Add `Doc::special_refs_quorum`, which reads the voters and threshold from
the rule governing the default branch, and falls back to the delegates and
their majority when there is none.
- Fall back the same way in `update::verify_delegates`, and read the branch
from the proposal rather than the repository, since that is the document
the delegates must serve once it is adopted.
Identity 2 made a resolvable `HEAD` a validity condition of every document.
That is stricter than upstream, where validity never depended on a default
branch, and it blocks repositories that hold no branches at all.
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index 95058510ae..39bd464a84 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -75,6 +75,8 @@ pub enum DocError {
Missing,
#[error("invalid default branch: {0}")]
DefaultBranch(#[from] DefaultBranchError),
+ #[error("invalid canonical references: {0}")]
+ CanonicalRefs(#[from] CanonicalRefsError),
}
#[derive(Debug, Error)]
@@ -495,6 +497,11 @@ impl Delegates {
self.0.iter()
}
+ /// The number of delegates that makes a majority of this set.
+ pub fn majority(&self) -> usize {
+ self.0.len() / 2 + 1
+ }
+
/// Check if the set contains the given `did`.
pub fn contains(&self, did: &Did) -> bool {
self.0.contains(did)
@@ -764,20 +771,52 @@ impl Doc {
///
/// The canonical references, including the default branch and its `HEAD`
/// symbolic reference, are governed entirely by the `xyz.radicle.crefs`
- /// payload. The payload must be present and must pass
+ /// payload.
+ ///
+ /// The payload is optional: a repository with no canonical references —
+ /// and therefore no default branch — has none. An absent payload yields
+ /// the empty set. A payload that is present must pass
/// [`RawCanonicalRefs::try_into_canonical_refs`] validation.
///
/// [`RawCanonicalRefs`]: super::crefs::RawCanonicalRefs
pub fn canonical_refs(&self) -> Result<CanonicalRefs, CanonicalRefsError> {
let raw_crefs = self
.raw_canonical_refs()
- .ok_or(CanonicalRefsError::Missing)?
- .map_err(CanonicalRefsError::Payload)?;
+ .transpose()
+ .map_err(CanonicalRefsError::Payload)?
+ .unwrap_or_default();
let resolve = &mut || self.delegates.clone();
Ok(raw_crefs.try_into_canonical_refs(resolve)?)
}
+ /// The peers who vote on this repository's special references, and how
+ /// many of their `rad/sigrefs` a fetch requires to be present.
+ ///
+ /// When the document names a default branch, both come from the crefs
+ /// rule that governs it, so that the threshold and the population it is
+ /// counted over agree. A repository with no default branch has no such
+ /// rule: the delegates and [`Doc::majority`] govern instead, which is
+ /// already the quorum for adopting an identity revision.
+ ///
+ /// Returns `None` when a `HEAD` is declared but no rule governs its
+ /// target, so that callers fail closed rather than assume a quorum. A
+ /// verified document cannot be in that state — [`RawDoc::verified`]
+ /// rejects a dangling `HEAD` — so this is a guard, not a path.
+ pub fn special_refs_quorum(&self) -> Result<Option<(Delegates, usize)>, CanonicalRefsError> {
+ let crefs = self.canonical_refs()?;
+ let Some(head) = crefs.symbolic().resolve_head() else {
+ return Ok(Some((self.delegates.clone(), self.majority())));
+ };
+
+ Ok(crefs.rules().matches(head).next().map(|(_, rule)| {
+ (
+ rule.allowed().deref().clone(),
+ usize::from(*rule.threshold()),
+ )
+ }))
+ }
+
/// Return the associated [`Visibility`] of this document.
pub fn visibility(&self) -> &Visibility {
&self.view.visibility
@@ -839,7 +878,7 @@ impl Doc {
/// Return the majority number based on the size of the delegates set.
pub fn majority(&self) -> usize {
- self.delegates.len() / 2 + 1
+ self.delegates.majority()
}
/// Helper for getting an `embeds` Git blob.
@@ -926,9 +965,6 @@ pub enum CanonicalRefsError {
#[error(transparent)]
CanonicalRefs(#[from] crefs::ValidationError),
-
- #[error("identity document is missing the `xyz.radicle.crefs` payload")]
- Missing,
}
#[cfg(test)]
@@ -1010,13 +1046,14 @@ mod test {
2,
Visibility::Public,
);
- assert_matches!(doc.verified(), Err(DocError::DefaultBranch(_)));
+ assert_matches!(doc.verified(), Err(DocError::CanonicalRefs(_)));
}
#[test]
- fn verified_rejects_missing_crefs() {
- // Without the `xyz.radicle.crefs` payload there is no default branch or
- // write quorum, so the document must not verify.
+ fn verified_accepts_missing_crefs() {
+ // Without the `xyz.radicle.crefs` payload there is no default branch,
+ // which is allowed: the payload governs canonical references, and a
+ // repository may have none. See `branch_free_document_is_valid`.
let mut doc = RawDoc::new(
r#gen::<Project>(1),
vec![r#gen::<Did>(1)],
@@ -1025,7 +1062,8 @@ mod test {
Visibility::Public,
);
doc.payload_mut().remove(PayloadId::canonical_refs());
- assert_matches!(doc.verified(), Err(DocError::DefaultBranch(_)));
+ let doc = doc.verified().unwrap();
+ assert_matches!(doc.default_branch(), Err(DefaultBranchError::MissingHead));
}
/// A version-1 document as a released client wrote it.
@@ -1604,8 +1642,62 @@ mod test {
let migrated = doc.migrated().unwrap();
assert_eq!(migrated.version(), IDENTITY_VERSION);
assert!(
- migrated.payload().get(PayloadId::canonical_refs()).is_none(),
+ migrated
+ .payload()
+ .get(PayloadId::canonical_refs())
+ .is_none(),
"no default branch to govern, so no crefs payload is synthesized"
);
}
+
+ /// With a default branch, the voters and the number of them required
+ /// come from the rule that governs it.
+ #[test]
+ fn special_refs_quorum_comes_from_the_branch_rule() {
+ let value = json!({
+ "version": 2,
+ "payload": {
+ "xyz.radicle.crefs": {
+ "symbolic": { "HEAD": "refs/heads/main" },
+ "rules": {
+ "refs/heads/main": { "allow": "delegates", "threshold": 2 }
+ }
+ }
+ },
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
+ "did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
+ "did:key:z6MkuPZWtx7g5rDgz9tpVKTiHVCrAqbtGwZuLb6a6z7ULHwv"
+ ]
+ });
+
+ let doc = serde_json::from_value::<Doc>(value).unwrap();
+ let (allowed, threshold) = doc.special_refs_quorum().unwrap().unwrap();
+
+ assert_eq!(threshold, 2);
+ assert_eq!(&allowed, doc.delegates());
+ }
+
+ /// Without a default branch there is no rule, so the delegates and
+ /// `Doc::majority` govern — the same quorum that adopts an identity
+ /// revision.
+ #[test]
+ fn special_refs_quorum_falls_back_to_majority() {
+ let value = json!({
+ "version": 2,
+ "payload": {},
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
+ "did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
+ "did:key:z6MkuPZWtx7g5rDgz9tpVKTiHVCrAqbtGwZuLb6a6z7ULHwv"
+ ]
+ });
+
+ let doc = serde_json::from_value::<Doc>(value).unwrap();
+ let (allowed, threshold) = doc.special_refs_quorum().unwrap().unwrap();
+
+ assert_eq!(threshold, doc.majority());
+ assert_eq!(threshold, 2);
+ assert_eq!(&allowed, doc.delegates());
+ }
}
diff --git a/crates/radicle/src/identity/doc/migrate.rs b/crates/radicle/src/identity/doc/migrate.rs
index bcb6e73f33..0dfc34f20d 100644
--- a/crates/radicle/src/identity/doc/migrate.rs
+++ b/crates/radicle/src/identity/doc/migrate.rs
@@ -40,11 +40,6 @@ pub enum Error {
#[error(transparent)]
Delegates(#[from] DelegatesError),
-
- #[error(
- "no default branch to migrate: the `xyz.radicle.project` payload defines no `defaultBranch` and the `xyz.radicle.crefs` payload defines no `HEAD` symbolic reference"
- )]
- MissingDefaultBranch,
}
/// The version-1 rule governing the default branch disagrees with the rest of
@@ -83,6 +78,11 @@ impl Migrate for v1::Doc {
/// document's `threshold`. That invariant is checked here rather than
/// papered over, so a document that never was valid does not become valid
/// by migrating.
+ ///
+ /// A document with neither a `defaultBranch` nor a crefs `HEAD` names no
+ /// default branch. It migrates to a version-2 document with no crefs
+ /// payload, rather than failing: a repository is allowed to have no
+ /// canonical references.
fn migrate(mut self) -> Result<Self::Next, Self::Error> {
let threshold = self.threshold;
let default_branch = self.default_branch();
@@ -125,7 +125,11 @@ impl Migrate for v1::Doc {
synthesize_head(&mut crefs, &valid, &branch, threshold);
true
}
- (None, None) => return Err(Error::MissingDefaultBranch),
+ // No default branch to migrate. The top-level `threshold` has
+ // nowhere to go, which costs nothing it governed: identity
+ // revisions are adopted by `Doc::majority`, and there is no
+ // branch rule to carry a quorum into.
+ (None, None) => false,
};
// The crefs payload is the sole authority from here on.
diff --git a/crates/radicle/src/identity/doc/raw.rs b/crates/radicle/src/identity/doc/raw.rs
index ebf5a84820..fa24060982 100644
--- a/crates/radicle/src/identity/doc/raw.rs
+++ b/crates/radicle/src/identity/doc/raw.rs
@@ -265,8 +265,9 @@ impl RawDoc {
/// top-level `threshold` and the crefs payload together.
/// - The migrated document satisfies the version-2 invariants: the
/// `xyz.radicle.project` payload defines no `defaultBranch`, and the
- /// `xyz.radicle.crefs` payload is present, valid, and defines a
- /// resolvable default branch whose rule has a well-formed write quorum
+ /// `xyz.radicle.crefs` payload — which is optional — is valid where
+ /// present, meaning every symbolic reference resolves to a ruled
+ /// target and every rule has a well-formed write quorum
/// (`1 <= threshold <= |allowed|`).
///
/// [`MAX_DELEGATES`]: super::MAX_DELEGATES
@@ -283,9 +284,13 @@ impl RawDoc {
};
// Validate here so that *every* verified `Doc` — including those adopted
// over the network via `Doc::from_blob` and those obtained by
- // deserializing — carries an enforceable quorum, rather than deferring
- // the check to the CLI-only `update::verify`.
- doc.default_branch()?;
+ // deserializing — carries enforceable canonical references, rather
+ // than deferring the check to the CLI-only `update::verify`.
+ //
+ // N.b. this validates the payload, it does not require one. A
+ // repository may have no canonical references, and so no default
+ // branch; what it may not have is a broken set of them.
+ doc.canonical_refs()?;
Ok(doc)
}
diff --git a/crates/radicle/src/identity/doc/update.rs b/crates/radicle/src/identity/doc/update.rs
index b47ef6a792..dc16c0474f 100644
--- a/crates/radicle/src/identity/doc/update.rs
+++ b/crates/radicle/src/identity/doc/update.rs
@@ -6,7 +6,7 @@ use serde_json as json;
use crate::{
prelude::Did,
- storage::{self, ReadRepository, RepositoryError, refs},
+ storage::{self, RepositoryError, refs},
};
use super::{Doc, GetPayload as _, PayloadError, PayloadId, RawDoc, Visibility};
@@ -216,8 +216,9 @@ pub fn verify(raw: RawDoc) -> Result<Doc, error::DocVerification> {
}
// Verify that the canonical references payload is valid. The default branch
- // and its `HEAD` symbolic reference are now governed entirely by the
- // `xyz.radicle.crefs` payload, which must be present and resolvable.
+ // and its `HEAD` symbolic reference are governed entirely by the
+ // `xyz.radicle.crefs` payload. The payload is optional — a repository may
+ // have no canonical references — but one that is present must resolve.
if let Err(e) = proposal.canonical_refs() {
return Err(error::DocVerification::PayloadError {
id: PayloadId::canonical_refs().clone(),
@@ -231,34 +232,56 @@ fn verify_delegates(
proposal: &RawDoc,
repo: &storage::git::Repository,
) -> Result<Option<Vec<error::DelegateVerification>>, RepositoryError> {
+ use std::ops::Deref as _;
+
use super::{CanonicalRefsError, Delegates, DocError, GetPayload as _};
- let (canonical, _) = repo.canonical_head()?;
- // The quorum for the canonical default branch is defined by the canonical
- // reference rule that matches it. Resolve the *validated* rule so that (a)
- // the most specific matching rule is chosen (the raw rules are only byte
- // ordered), and (b) both the required threshold and the population of
- // voters counted below come from that same rule. Fail closed: an unreadable
- // or invalid crefs payload, or a branch with no matching rule, is a
- // verification error, not an assumed quorum of 1.
let delegates = Delegates::new(proposal.delegates().iter().copied()).map_err(DocError::from)?;
// Read the rules from the *migrated* document, so that a document stored at
- // an older version is governed by the same rules its readers see.
+ // an older version is governed by the same rules its readers see. The crefs
+ // payload is optional, so an absent one yields no rules rather than an
+ // error; one that is present must still be valid.
let crefs = proposal
.view()
.map_err(DocError::from)?
.raw_canonical_refs()
- .ok_or(CanonicalRefsError::Missing)?
+ .transpose()
.map_err(CanonicalRefsError::Payload)?
+ .unwrap_or_default()
.try_into_canonical_refs(&mut || delegates.clone())
.map_err(CanonicalRefsError::from)?;
- let (_, rule) = crefs
- .rules()
- .matches(&canonical)
- .next()
- .ok_or(RepositoryError::MissingBranchRule)?;
- let allowed = rule.allowed();
- let threshold = usize::from(*rule.threshold());
+
+ // The quorum for the default branch is defined by the canonical reference
+ // rule that matches it. Resolve the *validated* rule so that (a) the most
+ // specific matching rule is chosen (the raw rules are only byte ordered),
+ // and (b) both the required threshold and the population of voters counted
+ // below come from that same rule. Fail closed: a branch with no matching
+ // rule is a verification error, not an assumed quorum of 1.
+ //
+ // N.b. the branch is read from the *proposal*, since that is the document
+ // the delegates must be able to serve once the change is adopted.
+ //
+ // A proposal that names no default branch has no such rule. The delegates
+ // and their majority govern instead, and there is no branch that a
+ // delegate could be missing.
+ let branch = crefs.symbolic().resolve_head();
+ let (allowed, threshold) = match &branch {
+ Some(branch) => {
+ let (_, rule) = crefs
+ .rules()
+ .matches(branch)
+ .next()
+ .ok_or(RepositoryError::MissingBranchRule)?;
+ (
+ rule.allowed().deref().clone(),
+ usize::from(*rule.threshold()),
+ )
+ }
+ None => {
+ let majority = delegates.majority();
+ (delegates, majority)
+ }
+ };
// Count the votes over the rule's `allowed` set, which may differ from the
// identity delegates when the default branch is governed by an explicit set.
@@ -271,9 +294,11 @@ fn verify_delegates(
missing.push(error::DelegateVerification::MissingDelegate { did: *did });
}
Some(sigrefs) => {
- if sigrefs.get(&canonical).is_none() {
+ if let Some(branch) = &branch
+ && sigrefs.get(branch).is_none()
+ {
missing.push(error::DelegateVerification::MissingDefaultBranch {
- branch: canonical.to_ref_string(),
+ branch: branch.to_ref_string(),
did: *did,
});
}
commit ed86a2b1146cdcf8acff38188122508890deb19e
Author: Daniel Norman <daniel@norman.life>
Date: Tue Sep 1 11:52:00 2026 +0200
radicle/identity: failing tests for branch-free docs
- Assert a version-2 document with no `xyz.radicle.crefs` payload, and one
with no payloads at all, are valid and simply cannot name a default branch.
- Assert a version-1 document with neither `defaultBranch` nor a crefs
`HEAD` stays readable and migrates.
- Guard the relaxation: a `HEAD` that no rule governs stays invalid.
Identity 2 made a resolvable `HEAD` a validity condition of every document,
which is stricter than upstream, where validity never depended on a default
branch. These tests pin the intended behaviour before the fix.
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index b9b3f2e04e..95058510ae 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -1511,4 +1511,101 @@ mod test {
assert_eq!(pattern.to_string(), "refs/heads/main");
assert_eq!(usize::from(*rule.threshold()), 1);
}
+
+ /// A repository need not have a default branch. A version-2 document
+ /// without a `xyz.radicle.crefs` payload is valid; it simply cannot name
+ /// one.
+ #[test]
+ fn branch_free_document_is_valid() {
+ let value = json!({
+ "version": 2,
+ "payload": {
+ "xyz.radicle.project": {
+ "name": "acme",
+ "description": "a repository with no default branch",
+ }
+ },
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
+ ]
+ });
+
+ let doc = serde_json::from_value::<Doc>(value).unwrap();
+
+ assert_matches!(doc.default_branch(), Err(DefaultBranchError::MissingHead));
+ let crefs = doc
+ .canonical_refs()
+ .expect("absent crefs payload yields empty canonical references");
+ assert!(crefs.symbolic().is_empty());
+ assert!(crefs.rules().is_empty());
+ }
+
+ /// A document need not carry any payload at all to be valid.
+ #[test]
+ fn payload_free_document_is_valid() {
+ let value = json!({
+ "version": 2,
+ "payload": {},
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
+ ]
+ });
+
+ let doc = serde_json::from_value::<Doc>(value).unwrap();
+
+ assert!(doc.project().is_none());
+ assert_matches!(doc.default_branch(), Err(DefaultBranchError::MissingHead));
+ }
+
+ /// Relaxing the default branch requirement must not relax the crefs
+ /// payload itself: a `HEAD` that no rule governs is still a broken
+ /// document, since its canonical head could not be established.
+ #[test]
+ fn dangling_head_is_still_invalid() {
+ let value = json!({
+ "version": 2,
+ "payload": {
+ "xyz.radicle.crefs": {
+ "symbolic": { "HEAD": "refs/heads/main" },
+ "rules": {}
+ }
+ },
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
+ ]
+ });
+
+ assert!(serde_json::from_value::<Doc>(value).is_err());
+ }
+
+ /// A version-1 document with neither `defaultBranch` nor a crefs `HEAD`
+ /// must stay readable, and must migrate. Its top-level `threshold` has
+ /// nowhere to go, which costs nothing: it never governed identity
+ /// adoption, and there is no branch rule to carry it into.
+ #[test]
+ fn branch_free_v1_document_migrates() {
+ let value = json!({
+ "payload": {
+ "xyz.radicle.project": {
+ "name": "acme",
+ "description": "a repository with no default branch",
+ }
+ },
+ "delegates": [
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
+ ],
+ "threshold": 1
+ });
+
+ let doc = serde_json::from_value::<Doc>(value).unwrap();
+ assert_eq!(doc.version(), Version::new(1).unwrap());
+ assert_matches!(doc.default_branch(), Err(DefaultBranchError::MissingHead));
+
+ let migrated = doc.migrated().unwrap();
+ assert_eq!(migrated.version(), IDENTITY_VERSION);
+ assert!(
+ migrated.payload().get(PayloadId::canonical_refs()).is_none(),
+ "no default branch to govern, so no crefs payload is synthesized"
+ );
+ }
}
commit 71694a2d8ee989c6f6970b2307612faf2c62f034
Author: Daniel Norman <daniel@norman.life>
Date: Thu Aug 13 17:58:24 2026 +0200
radicle: identity 2 and default branch with crefs
The default branch was the one canonical reference the
`xyz.radicle.crefs` payload was not allowed to govern. Its name lived in
the `defaultBranch` field of the `xyz.radicle.project` payload and its
quorum in the identity document's top-level `threshold`, from which the
rule and the `HEAD` symbolic reference were synthesized as
`Allowed::Delegates` at that threshold. A document that stated either
itself was rejected: `update::verify` refused a crefs payload defining
`HEAD`, or any rule matching `defaultBranch`. So the default branch alone
could not be governed by a narrower set, unlike every other canonical
branch.
Counting votes followed the document, not the rule. A fetch used the
document `threshold` as the number of delegates it must validate before
it applies any update, so the rule governing the branch it established
never set its own quorum.
Make the `xyz.radicle.crefs` payload the sole authority over the
canonical head. The rule whose pattern matches the `HEAD` symbolic
reference now defines the default branch, its `allow` set and its
threshold:
- Remove `defaultBranch` and the top-level `threshold`, and synthesize
the default-branch rule and its `HEAD` symbolic reference on document
creation.
- Take the fetch quorum from the rule matching the canonical head: the
special-refs anchor counts votes from the rule's `allow` set against
the rule's threshold, so the counted peers and the number required come
from one place.
- Fail closed in verification and in fetch when no rule matches, because
an unresolvable canonical head leaves the repository unloadable.
Identity revisions stay on a simple delegate majority.
- Route callers through the identity document, adding
`ReadRepository::default_branch_name` and threading the branch from
`rad::init` to `Doc::initial`.
- Give `rad id` an in-place threshold update that preserves the rule's
`allow` set.
Bump `IDENTITY_VERSION` to 2, and keep version 1 documents readable so
existing repositories survive the upgrade:
- Make `RawDoc` an enum over the version 1 and version 2 stored schemas,
each with its own serialization, so a version 1 document re-encodes
byte-for-byte as released clients wrote it. The repository id and every
signature over the document are therefore unchanged.
- Hold both forms in `Doc`: the stored form decides identity, signing and
serialization; the migrated view is what every reader consumes. This
keeps version conditionals out of reader code.
- Derive the view with one `Migrate` implementation, which also produces
the document `rad id migrate` proposes, so the implicit and the
explicit migration cannot drift apart.
- Enforce the invariants per version: version 1 requires `threshold`,
and its migration checks that a crefs payload it already carries agrees
with `defaultBranch` and that threshold. Version 2 rejects a top-level
`threshold` when deserializing, and a `defaultBranch` when validating,
which `Project` would otherwise swallow as an unknown field.
- Keep an ordinary edit on the stored version, so only an explicit
migration changes it.
Add `rad id migrate`, which proposes the migrated document as a revision
the delegates vote on, and `rad init --identity-version` for a repository
that must stay readable to older releases. Adopting the migration is
opt-in per repository, because it is a one-way door: version 2 is
unreadable to releases 1.10.0 and earlier.
Sign the stored blob in `Revision::sign` rather than a re-encoding of the
in-memory document. Verification already checks the signature against the
stored blob, so any disagreement between the two silently broke votes.
Box the success side of `FetchResult::Initiator`. It carries a `DocAt`,
which grows with the stored-plus-view `Doc` from 168 to 264 bytes, so
`clippy` flags the size difference between the variants.
Update the tests, CLI examples and fixtures: repository and derived
collaborative-object ids change with the new identity root, dumps carry
the `xyz.radicle.crefs` payload and `"version": 2`, and the cases that
raised a document-level threshold are dropped since that knob moved into
the crefs payload.
Co-authored-by: Yorgos Saslis <yorgos.work@proton.me>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 675a94bcab..80fee11ded 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
+### Repository Identity: Canonical Default Branch and Document Version 2
+
+The default branch and the quorum required to write it are now governed by the
+canonical-reference rule in the `xyz.radicle.crefs` payload whose pattern
+matches the `HEAD` symbolic reference. The `defaultBranch` field of the
+`xyz.radicle.project` payload and the top-level `threshold` have been removed,
+and the default branch is no longer synthesized from `defaultBranch`. This
+allows non-delegates to hold canonical write access to a branch while delegates
+continue to govern identity updates.
+
+Because this changes the identity document format, the document version is now
+`2`. Newly created documents record `"version": 2` explicitly.
+
+Version 1 documents stay supported. A version 1 document is migrated to version
+2 in memory each time it is read, so every reader sees the current shape while
+the document on disk, and therefore the repository identifier and every
+signature over it, is unchanged. The default branch and its quorum are read from
+`defaultBranch` and `threshold` and expressed as a canonical-reference rule.
+Ordinary edits keep a document at its stored version.
+
+To move a repository to version 2, run `rad id migrate`. This proposes the
+migrated document as a new revision, which the delegates vote on like any other
+change. Once it is adopted the repository is no longer readable to releases
+1.10.0 and earlier, so the migration is opt-in per repository.
+
+`rad init --identity-version 1` writes a version 1 document, for a repository
+that must stay readable to older releases.
+
## Fixes
- A patch now merges on the quorum of the canonical reference rule that
diff --git a/crates/radicle-cli/examples/git/git-fetch.md b/crates/radicle-cli/examples/git/git-fetch.md
index 40784ed1d6..f8d9c15c0b 100644
--- a/crates/radicle-cli/examples/git/git-fetch.md
+++ b/crates/radicle-cli/examples/git/git-fetch.md
@@ -13,7 +13,7 @@ f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
``` (stderr)
$ git fetch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] alice/1 -> alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/alice/1
```
diff --git a/crates/radicle-cli/examples/git/git-push-amend.md b/crates/radicle-cli/examples/git/git-push-amend.md
index 4fe8d313ff..63eea87f07 100644
--- a/crates/radicle-cli/examples/git/git-push-amend.md
+++ b/crates/radicle-cli/examples/git/git-push-amend.md
@@ -1,11 +1,11 @@
``` ~alice
-$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -q
-c036c0d89ce26aef3ad7da402157dba16b5163b4
+$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G -q
+03c1bd2e277d5d4850a0021f954c188155f332d5
```
``` ~bob
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -23,6 +23,6 @@ $ git commit --amend -m "Neue Änderungen" --allow-empty -q
$ git push rad master -f
✓ Canonical reference refs/heads/master updated to target commit 9170c8795d3a78f0381a0ffafb20ea69fb0f5b6b
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ fb25886...9170c87 master -> master (forced update)
```
diff --git a/crates/radicle-cli/examples/git/git-push-canonical-annotated-tags.md b/crates/radicle-cli/examples/git/git-push-canonical-annotated-tags.md
index 7bfefcc481..a00b753c43 100644
--- a/crates/radicle-cli/examples/git/git-push-canonical-annotated-tags.md
+++ b/crates/radicle-cli/examples/git/git-push-canonical-annotated-tags.md
@@ -46,13 +46,13 @@ case, we will have two rules: one for `refs/tags/*` and one for `refs/tags/qa/*`
(see RIP-0004 for more information on the rules).
``` ~alice
-$ rad id update --title "Add canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
+$ rad id update --title "Add canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
✓ Identity revision [..] created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add canonical reference rules │
-│ Revision c3349f07bfe6a82bbeb2989d2de4a918408f9831 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob 85fa09e2de93b825d5231778dbb34143004a4bca │
+│ Revision 0ae3d527cf77ceb980ffc7db8074201233957d71 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 4d4f5c7c7577730f96de5807e937831333d59458 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -60,11 +60,16 @@ $ rad id update --title "Add canonical reference rules" --payload xyz.radicle.cr
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,25 @@
+@@ -1,23 +1,31 @@
{
+ "version": 2,
"payload": {
-+ "xyz.radicle.crefs": {
-+ "rules": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
++ },
+ "refs/tags/*": {
+ "allow": "delegates",
+ "threshold": 1
@@ -72,19 +77,20 @@ $ rad id update --title "Add canonical reference rules" --payload xyz.radicle.cr
+ "refs/tags/qa/*": {
+ "allow": "delegates",
+ "threshold": 1
-+ }
-+ }
-+ },
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
@@ -100,7 +106,7 @@ tag
$ git push rad --tags
✓ Canonical reference refs/tags/v1.0-hotfix updated to target tag ac51a0746a5e8311829bc481202909a1e3acc0c2
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0-hotfix -> v1.0-hotfix
```
@@ -116,7 +122,7 @@ On the other side, Bob performs a fetch and now has the tags locally:
``` ~bob (stderr)
$ cd heartwood
$ git fetch rad
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
* [new tag] v1.0-hotfix -> rad/tags/v1.0-hotfix
* [new tag] v1.0-hotfix -> v1.0-hotfix
```
@@ -136,7 +142,7 @@ the `threshold` to `2` for the `refs/tags/*` rule:
``` ~bob
$ rad remote add z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Follow policy updated for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote alice added
✓ Remote-tracking branch alice/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -146,14 +152,14 @@ $ git push rad master
``` ~alice
$ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --name bob
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote bob added
✓ Remote-tracking branch bob/master created for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
-27ab0d77a95581c59ca9d30e679ceb06a9f758db
-$ rad id update --title "Update canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/tags/*": { "threshold": 2, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" } }' -q
-dace164ba43fa51802697ec28d0b1965a9d7808b
+ed314851757c39be4edf1f87b7d7beab0ba3d62f
+$ rad id update --title "Update canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/tags/*": { "threshold": 2, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" } }' -q
+f3137e0cb6426f325779947c9ffc619b0f3f225d
```
**Note:** here we have to specify all the rules again to update the `threshold`.
@@ -162,10 +168,10 @@ editor instead.
``` ~bob
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-$ rad id accept dace164ba43fa51802697ec28d0b1965a9d7808b -q
+$ rad id accept f3137e0cb6426f325779947c9ffc619b0f3f225d -q
```
When Bob creates a new tag and pushes it, we see that there's a warning that
@@ -184,7 +190,7 @@ $ git push rad --tags
warn: could not determine target for canonical reference 'refs/tags/v2.0', no object with at least 2 vote(s) found (threshold not met)
warn: it is recommended to find an object (either commit or tag) to agree upon
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] v1.0-hotfix -> v1.0-hotfix
* [new tag] v2.0 -> v2.0
```
@@ -194,7 +200,7 @@ it:
``` ~alice (stderr)
$ git fetch bob
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] v1.0-hotfix -> bob/tags/v1.0-hotfix
* [new tag] v2.0 -> bob/tags/v2.0
```
@@ -210,7 +216,7 @@ $ git tag v2.0 bob/tags/v2.0
$ git push rad --tags
✓ Canonical reference refs/tags/v2.0 updated to target tag 89f935f27a16f8ed97915ade4accab8fe48057aa
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v2.0 -> v2.0
```
@@ -227,6 +233,6 @@ $ git tag qa/v2.1
$ git push rad --tags
✓ Canonical reference refs/tags/qa/v2.1 updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] qa/v2.1 -> qa/v2.1
```
diff --git a/crates/radicle-cli/examples/git/git-push-canonical-branch.md b/crates/radicle-cli/examples/git/git-push-canonical-branch.md
index 97e858f18e..d39a159d40 100644
--- a/crates/radicle-cli/examples/git/git-push-canonical-branch.md
+++ b/crates/radicle-cli/examples/git/git-push-canonical-branch.md
@@ -1,11 +1,11 @@
``` ~alice
-$ rad id update --title "Add canonical branch for releases" --payload xyz.radicle.crefs rules '{ "refs/heads/releases/*": { "threshold": 1, "allow": [ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk" ] }, "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
-✓ Identity revision [..] created
+$ rad id update --title "Add canonical branch for releases" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/releases/*": { "threshold": 1, "allow": [ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk" ] }, "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
+✓ Identity revision eb3f118684b846c352e6b7f2bb97bf8ac7edad2d created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add canonical branch for releases │
-│ Revision 37a1aad231100cd206c49aed79e405ea2da9204b │
-│ Parent dace164ba43fa51802697ec28d0b1965a9d7808b │
-│ Blob bbefd77cfeb456e500ad868c3b4effe1f7f818e2 │
+│ Revision eb3f118684b846c352e6b7f2bb97bf8ac7edad2d │
+│ Parent f3137e0cb6426f325779947c9ffc619b0f3f225d │
+│ Blob ec43d69ba56e3595f19d66fe7b1fca690491e477 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │
│ Quorum no │
@@ -14,11 +14,16 @@ $ rad id update --title "Add canonical branch for releases" --payload xyz.radicl
│ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,26 +1,32 @@
+@@ -1,32 +1,38 @@
{
+ "version": 2,
"payload": {
"xyz.radicle.crefs": {
"rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ },
+ "refs/heads/releases/*": {
+ "allow": [
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
@@ -34,10 +39,12 @@ $ rad id update --title "Add canonical branch for releases" --payload xyz.radicl
"allow": "delegates",
"threshold": 1
}
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
}
},
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -45,18 +52,17 @@ $ rad id update --title "Add canonical branch for releases" --payload xyz.radicl
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 1
+ ]
}
```
``` ~bob
$ cd heartwood
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-$ rad id accept 37a1aad231100cd206c49aed79e405ea2da9204b -q
+$ rad id accept eb3f118684b846c352e6b7f2bb97bf8ac7edad2d -q
```
Bob immediately pushes a branch that matches the rule, thus populating and
@@ -72,13 +78,13 @@ $ git commit --allow-empty --message "Release notes for version 2"
$ git push -u rad releases/2
✓ Canonical reference refs/heads/releases/2 updated to target commit afec366785ed3651cdc66975c0fec41866c9ce62
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new branch] releases/2 -> releases/2
```
``` ~alice
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ git ls-remote rad
diff --git a/crates/radicle-cli/examples/git/git-push-canonical-lightweight-tags.md b/crates/radicle-cli/examples/git/git-push-canonical-lightweight-tags.md
index 5c4ed53a57..b42d7fd8b4 100644
--- a/crates/radicle-cli/examples/git/git-push-canonical-lightweight-tags.md
+++ b/crates/radicle-cli/examples/git/git-push-canonical-lightweight-tags.md
@@ -46,13 +46,13 @@ case, we will have two rules: one for `refs/tags/*` and one for `refs/tags/qa/*`
(see RIP-0004 for more information on the rules).
``` ~alice
-$ rad id update --title "Add canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
+$ rad id update --title "Add canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/tags/*": { "threshold": 1, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" }}'
✓ Identity revision [..] created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add canonical reference rules │
-│ Revision c3349f07bfe6a82bbeb2989d2de4a918408f9831 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob 85fa09e2de93b825d5231778dbb34143004a4bca │
+│ Revision 0ae3d527cf77ceb980ffc7db8074201233957d71 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 4d4f5c7c7577730f96de5807e937831333d59458 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -60,11 +60,16 @@ $ rad id update --title "Add canonical reference rules" --payload xyz.radicle.cr
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,25 @@
+@@ -1,23 +1,31 @@
{
+ "version": 2,
"payload": {
-+ "xyz.radicle.crefs": {
-+ "rules": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
++ },
+ "refs/tags/*": {
+ "allow": "delegates",
+ "threshold": 1
@@ -72,19 +77,20 @@ $ rad id update --title "Add canonical reference rules" --payload xyz.radicle.cr
+ "refs/tags/qa/*": {
+ "allow": "delegates",
+ "threshold": 1
-+ }
-+ }
-+ },
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
@@ -98,7 +104,7 @@ $ git tag v1.0-hotfix
$ git push rad --tags
✓ Canonical reference refs/tags/v1.0-hotfix updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0-hotfix -> v1.0-hotfix
```
@@ -114,7 +120,7 @@ On the other side, Bob performs a fetch and now has the tags locally:
``` ~bob (stderr)
$ cd heartwood
$ git fetch rad
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
* [new tag] v1.0-hotfix -> rad/tags/v1.0-hotfix
* [new tag] v1.0-hotfix -> v1.0-hotfix
```
@@ -134,7 +140,7 @@ the `threshold` to `2` for the `refs/tags/*` rule:
``` ~bob
$ rad remote add z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Follow policy updated for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote alice added
✓ Remote-tracking branch alice/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -144,14 +150,14 @@ $ git push rad master
``` ~alice
$ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --name bob
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote bob added
✓ Remote-tracking branch bob/master created for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
-27ab0d77a95581c59ca9d30e679ceb06a9f758db
-$ rad id update --title "Update canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/tags/*": { "threshold": 2, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" } }' -q
-dace164ba43fa51802697ec28d0b1965a9d7808b
+ed314851757c39be4edf1f87b7d7beab0ba3d62f
+$ rad id update --title "Update canonical reference rules" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/tags/*": { "threshold": 2, "allow": "delegates" }, "refs/tags/qa/*": { "threshold": 1, "allow": "delegates" } }' -q
+f3137e0cb6426f325779947c9ffc619b0f3f225d
```
**Note:** here we have to specify all the rules again to update the `threshold`.
@@ -160,10 +166,10 @@ editor instead.
``` ~bob
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-$ rad id accept dace164ba43fa51802697ec28d0b1965a9d7808b -q
+$ rad id accept f3137e0cb6426f325779947c9ffc619b0f3f225d -q
```
When Bob creates a new tag and pushes it, we see that there's a warning that
@@ -175,7 +181,7 @@ $ git push rad --tags
warn: could not determine target for canonical reference 'refs/tags/v2.0', no object with at least 2 vote(s) found (threshold not met)
warn: it is recommended to find an object (either commit or tag) to agree upon
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] v1.0-hotfix -> v1.0-hotfix
* [new tag] v2.0 -> v2.0
```
@@ -185,7 +191,7 @@ it:
``` ~alice (stderr)
$ git fetch bob
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] v1.0-hotfix -> bob/tags/v1.0-hotfix
* [new tag] v2.0 -> bob/tags/v2.0
```
@@ -201,7 +207,7 @@ $ git tag v2.0 bob/tags/v2.0
$ git push rad --tags
✓ Canonical reference refs/tags/v2.0 updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v2.0 -> v2.0
```
@@ -218,6 +224,6 @@ $ git tag qa/v2.1
$ git push rad --tags
✓ Canonical reference refs/tags/qa/v2.1 updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new tag] qa/v2.1 -> qa/v2.1
```
diff --git a/crates/radicle-cli/examples/git/git-push-canonical-symbolic-ref.md b/crates/radicle-cli/examples/git/git-push-canonical-symbolic-ref.md
index 49fa4e623f..497c6d3255 100644
--- a/crates/radicle-cli/examples/git/git-push-canonical-symbolic-ref.md
+++ b/crates/radicle-cli/examples/git/git-push-canonical-symbolic-ref.md
@@ -3,13 +3,13 @@ out symbolic references.
``` ~bob
$ cd heartwood
-$ rad id update --title "Add canonical symbolic ref" --payload xyz.radicle.crefs symbolic '{ "refs/heads/foobar": "refs/heads/releases/foobaz" }'
+$ rad id update --title "Add canonical symbolic ref" --payload xyz.radicle.crefs symbolic '{ "refs/heads/foobar": "refs/heads/releases/foobaz", "HEAD": "refs/heads/master" }'
✓ Identity revision [..] created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add canonical symbolic ref │
-│ Revision b7597e3eeaba64467db4417602518169b76b43d5 │
-│ Parent 37a1aad231100cd206c49aed79e405ea2da9204b │
-│ Blob 49a21614cf358b131fd6b590d0d01396f98906ce │
+│ Revision 0331767866ce4d4e040490ee42b262e5bf0d07b7 │
+│ Parent eb3f118684b846c352e6b7f2bb97bf8ac7edad2d │
+│ Blob 38b2a3c51cd46c1388dfec6f3faf4eca3e5fde94 │
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State active │
│ Quorum no │
@@ -18,11 +18,16 @@ $ rad id update --title "Add canonical symbolic ref" --payload xyz.radicle.crefs
│ ? did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,32 +1,35 @@
+@@ -1,38 +1,39 @@
{
+ "version": 2,
"payload": {
"xyz.radicle.crefs": {
"rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ },
"refs/heads/releases/*": {
"allow": [
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
@@ -37,13 +42,14 @@ $ rad id update --title "Add canonical symbolic ref" --payload xyz.radicle.crefs
"allow": "delegates",
"threshold": 1
}
-+ },
-+ "symbolic": {
+ },
+ "symbolic": {
+- "HEAD": "refs/heads/master"
++ "HEAD": "refs/heads/master",
+ "refs/heads/foobar": "refs/heads/releases/foobaz"
}
},
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -51,8 +57,7 @@ $ rad id update --title "Add canonical symbolic ref" --payload xyz.radicle.crefs
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 1
+ ]
}
```
@@ -68,10 +73,10 @@ revision.
``` ~alice
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-$ rad id accept b7597e3eeaba64467db4417602518169b76b43d5 -q
+$ rad id accept 0331767866ce4d4e040490ee42b262e5bf0d07b7 -q
```
As usual, alice works on "master".
@@ -87,7 +92,7 @@ And updating the canonical reference for "master" also works as usual.
$ git push rad
✓ Canonical reference refs/heads/master updated to target commit 4dc510ddea5fd66499d1d2e996b8a97c8d57be54
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..4dc510d master -> master
```
@@ -110,7 +115,7 @@ Of course, she can also fetch it to her working copy as usual.
``` ~alice (stderr)
$ git fetch rad
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
* [new branch] foobar -> rad/foobar
* [new branch] releases/2 -> rad/releases/2
* [new branch] releases/foobaz -> rad/releases/foobaz
@@ -122,7 +127,7 @@ Bob fetches Alice's changes.
``` ~bob
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -131,7 +136,7 @@ And, sure enough, there is the new branch just as he wanted it.
``` ~bob (stderr)
$ git fetch rad
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
* [new branch] foobar -> rad/foobar
f2de534..4dc510d master -> rad/master
```
diff --git a/crates/radicle-cli/examples/git/git-push-converge.md b/crates/radicle-cli/examples/git/git-push-converge.md
index 49e337119b..771baafc70 100644
--- a/crates/radicle-cli/examples/git/git-push-converge.md
+++ b/crates/radicle-cli/examples/git/git-push-converge.md
@@ -5,8 +5,8 @@ First we add our new delegates, Bob & Eve, to our repo, while also setting the
`threshold` to `3`:
``` ~alice
-$ rad id update --title "Add Bob & Eve" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --threshold 3 --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -q
-3143236b2e40338f5574ec04e935a5ab80a6868a
+$ rad id update --title "Add Bob & Eve" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --threshold 3 --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G -q
+5fedc54a1814be92fc6f0e296e6ce4af236fb6cf
```
Bob and Eve will fetch the changes to ensure they hear about their delegate
@@ -14,7 +14,7 @@ responsibilities:
``` ~bob
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -22,7 +22,7 @@ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential s
``` ~eve
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -63,13 +63,13 @@ found` error is showing up:
``` ~alice
$ rad remote add did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --name bob
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
✓ Remote bob added
✓ Remote-tracking branch bob/master created for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad remote add did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --name eve
✓ Follow policy updated for z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z (eve)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
✓ Remote eve added
✓ Remote-tracking branch eve/master created for z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
@@ -97,14 +97,14 @@ $ git push rad -f
warn: could not determine target for canonical reference 'refs/heads/master', no object with at least 3 vote(s) found (threshold not met)
warn: it is recommended to find an object (either commit or tag) to agree upon
✓ Synced with 2 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
d09e634..0f9bd80 master -> master
```
``` ~bob
$ rad remote add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Follow policy updated for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
✓ Remote alice added
✓ Remote-tracking branch alice/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -121,7 +121,7 @@ become the canonical `master`.
$ git push rad
✓ Canonical reference refs/heads/master updated to target commit 3a75f66dd0020c9a0355cc6ec21f15de989e2001
✓ Synced with 2 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
2a37862..0f9bd80 master -> master
```
@@ -130,7 +130,7 @@ Once Eve also resets to the merge commits, the canonical `master` is set to this
``` ~eve
$ rad remote add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Follow policy updated for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
✓ Remote alice added
✓ Remote-tracking branch alice/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -142,6 +142,6 @@ HEAD is now at 0f9bd80 Merge remote-tracking branch 'eve/master'
$ git push rad
✓ Canonical reference refs/heads/master updated to target commit 0f9bd8035c04b3f73f5408e73e8454879b20800b
✓ Synced with 2 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
3a75f66..0f9bd80 master -> master
```
diff --git a/crates/radicle-cli/examples/git/git-push-delete.md b/crates/radicle-cli/examples/git/git-push-delete.md
index 0d4edb5e51..3ae52338b3 100644
--- a/crates/radicle-cli/examples/git/git-push-delete.md
+++ b/crates/radicle-cli/examples/git/git-push-delete.md
@@ -1,7 +1,7 @@
Finally, we can also delete branches with `git push`:
```
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/*
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/*
145e1e69bef3ad93d14946ea212249c2fa9b9828 refs/heads/alice/1
ddcc1f164eacfd7dba41da9bff3261da3ee79fd3 refs/heads/alice/2
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
@@ -9,12 +9,12 @@ f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad :alice/1
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- [deleted] alice/1
```
```
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/*
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/*
ddcc1f164eacfd7dba41da9bff3261da3ee79fd3 refs/heads/alice/2
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
```
@@ -23,13 +23,13 @@ f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
$ git checkout alice/2
Switched to a new branch 'alice/2'
$ git push rad HEAD:refs/patches
-✓ Patch bb9b0d5b8de8d5e2a4cba45f02bd35b3e2678fbe opened
+✓ Patch fdb6ac2eb47ca76c9832dbc078d8ad4ef7cc17ee opened
To [..]
* [new reference] HEAD -> refs/patches
```
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad alice/2 -d
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- [deleted] alice/2
```
diff --git a/crates/radicle-cli/examples/git/git-push-diverge.md b/crates/radicle-cli/examples/git/git-push-diverge.md
index 4a79a1aa1b..36f9f51f7b 100644
--- a/crates/radicle-cli/examples/git/git-push-diverge.md
+++ b/crates/radicle-cli/examples/git/git-push-diverge.md
@@ -4,15 +4,15 @@ canonical head.
First we add a second delegate, Bob, to our repo:
``` ~alice
-$ rad id update --title "Add Bob" --description "" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -q
-c036c0d89ce26aef3ad7da402157dba16b5163b4
+$ rad id update --title "Add Bob" --description "" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G -q
+03c1bd2e277d5d4850a0021f954c188155f332d5
```
Then, as Bob, we commit some code on top of the canonical head:
``` ~bob
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ rad inspect --delegates
@@ -46,7 +46,7 @@ $ git push rad
warn: could not determine target commit for canonical reference 'refs/heads/master', found diverging commits 2e8758fc512cbdef298c86feddff5ba3280e94b4 and 319a7dc3b195368ded4b099f8c90bbb80addccd3, with base commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 and threshold 1
warn: it is recommended to find a commit to agree upon
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..2e8758f master -> master
```
@@ -63,7 +63,7 @@ f2de534 Second commit
``` ~alice RAD_SOCKET=/dev/null (stderr)
$ git push rad -f
✓ Canonical reference refs/heads/master updated to target commit f6cff86594495e9beccfeda7c20173e55c1dd9fc
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 2e8758f...f6cff86 master -> master (forced update)
```
@@ -76,6 +76,6 @@ $ git reset --hard HEAD^ -q
``` ~alice RAD_SOCKET=/dev/null (stderr)
$ git push -f
✓ Canonical reference refs/heads/master updated to target commit 319a7dc3b195368ded4b099f8c90bbb80addccd3
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f6cff86...319a7dc master -> master (forced update)
```
diff --git a/crates/radicle-cli/examples/git/git-push-force-with-lease.md b/crates/radicle-cli/examples/git/git-push-force-with-lease.md
index 4e92588ae6..70a88840b4 100644
--- a/crates/radicle-cli/examples/git/git-push-force-with-lease.md
+++ b/crates/radicle-cli/examples/git/git-push-force-with-lease.md
@@ -18,7 +18,7 @@ the last time you pushed.
$ git commit --amend -m "Neue Änderungen" --allow-empty -q
$ git push rad master --force-with-lease
✓ Canonical reference refs/heads/master updated to target commit 9170c8795d3a78f0381a0ffafb20ea69fb0f5b6b
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ fb25886...9170c87 master -> master (forced update)
```
@@ -29,7 +29,7 @@ value, to `--force-push-lease`:
$ git commit --amend -m "Noch mehr Änderungen" --allow-empty -q
$ git push rad master --force-with-lease=master
✓ Canonical reference refs/heads/master updated to target commit 1e4213811eb4ce67360e4a0222cab81ad11a7ffe
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 9170c87...1e42138 master -> master (forced update)
```
@@ -39,7 +39,7 @@ As well as the named reference, and its expected value:
$ git commit --amend -m "Even more changes" --allow-empty -q
$ git push rad master --force-with-lease=master:1e4213811eb4ce67360e4a0222cab81ad11a7ffe
✓ Canonical reference refs/heads/master updated to target commit c4b74ef30953598852a82e0cd22b2ebb0d8d9e18
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 1e42138...c4b74ef master -> master (forced update)
```
@@ -52,9 +52,9 @@ $ git commit --amend -m "And even more" --allow-empty -q
``` (stderr) (fail)
$ git push rad master --force-with-lease=master:1e4213811eb4ce67360e4a0222cab81ad11a7ffe
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
! [rejected] master -> master (stale info)
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
```
And if we do not supply the commit, it should also fail, since this implies that
@@ -66,16 +66,16 @@ $ git commit --amend -m "And even more" --allow-empty -q
``` (stderr) (fail)
$ git push rad master --force-with-lease=master:
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
! [rejected] master -> master (stale info)
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
```
So, let's create a new branch:
``` (stderr)
$ git push rad master:dev --force-with-lease=dev:
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] master -> dev
```
diff --git a/crates/radicle-cli/examples/git/git-push-rollback.md b/crates/radicle-cli/examples/git/git-push-rollback.md
index 7b23a0a7af..4a0c09a091 100644
--- a/crates/radicle-cli/examples/git/git-push-rollback.md
+++ b/crates/radicle-cli/examples/git/git-push-rollback.md
@@ -4,15 +4,15 @@ First we add a second delegate, Bob, to our repo. We also change the threshold
to 2:
``` ~alice
-$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --threshold 2 -q
-069e7d58faa9a7473d27f5510d676af33282796f
+$ rad id update --title "Add Bob" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --threshold 2 -q
+c7d68a801ed8c107521cb63b4089b4bd6601fad4
```
Bob then syncs these changes and adds a new commit:
``` ~bob
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ git commit -m "Third commit" --allow-empty -q
@@ -37,7 +37,7 @@ Fast-forward
$ git push rad
✓ Canonical reference refs/heads/master updated to target commit 319a7dc3b195368ded4b099f8c90bbb80addccd3
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..319a7dc master -> master
```
@@ -56,6 +56,6 @@ push and the new canonical head becomes the previous commit again:
$ git push rad -f
✓ Canonical reference refs/heads/master updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 319a7dc...f2de534 master -> master (forced update)
```
diff --git a/crates/radicle-cli/examples/git/git-push.md b/crates/radicle-cli/examples/git/git-push.md
index 2c24faaf49..0019c01c56 100644
--- a/crates/radicle-cli/examples/git/git-push.md
+++ b/crates/radicle-cli/examples/git/git-push.md
@@ -6,7 +6,7 @@ $ git commit -m "Alice's commit" --allow-empty -s
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad HEAD:alice/1
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] HEAD -> alice/1
```
@@ -17,9 +17,9 @@ $ git commit --amend -m "Alice's amended commit" --allow-empty -s
```
``` (stderr) (fail)
$ git push rad HEAD:alice/1
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
! [rejected] HEAD -> alice/1 (non-fast-forward)
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
hint: [..]
hint: [..]
hint: [..]
@@ -30,7 +30,7 @@ And that we can with `+`:
``` (stderr)
$ git push -o no-sync rad +HEAD:alice/1
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 87fa120...145e1e6 HEAD -> alice/1 (forced update)
```
@@ -45,7 +45,7 @@ $ git branch -r -vv
List our namespaced refs:
```
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/*'
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/heads/*'
145e1e69bef3ad93d14946ea212249c2fa9b9828 refs/heads/alice/1
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
```
@@ -68,7 +68,7 @@ Note that it is forbidden to delete the default/canonical branch:
``` (fail) (stderr)
$ git push rad :master
error: refusing to delete default branch ref 'refs/heads/master'
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
```
If you pass an unsupported push option, you get an error:
@@ -86,6 +86,6 @@ $ git commit -m "Something good" --allow-empty -s
```
``` (stderr)
$ git push -o no-sync rad ddcc1f164eacfd7dba41da9bff3261da3ee79fd3:refs/heads/alice/2
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] ddcc1f164eacfd7dba41da9bff3261da3ee79fd3 -> alice/2
```
diff --git a/crates/radicle-cli/examples/git/git-tag.md b/crates/radicle-cli/examples/git/git-tag.md
index 365bda7015..d53025a76e 100644
--- a/crates/radicle-cli/examples/git/git-tag.md
+++ b/crates/radicle-cli/examples/git/git-tag.md
@@ -13,7 +13,7 @@ $ git tag v1.0 -a -m "Release v1.0"
``` ~alice (stderr)
$ git push rad v1.0
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0 -> v1.0
```
@@ -37,7 +37,7 @@ Bob fetches the tag from Alice, by adding her as a remote:
$ cd heartwood
$ rad remote add z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --name alice
✓ Follow policy updated for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote alice added
✓ Remote-tracking branch alice/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -48,7 +48,7 @@ under the `alice` remote:
``` ~bob (stderr)
$ git fetch alice
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new tag] v1.0 -> alice/tags/v1.0
```
@@ -65,7 +65,7 @@ Updated tag 'v1.0' (was be18ed6)
``` ~alice (stderr)
$ git push rad v1.0 -f
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ be18ed6...9dbdebc v1.0 -> v1.0 (forced update)
```
@@ -74,13 +74,13 @@ update of the tag:
``` ~bob
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
``` ~bob (stderr)
$ git fetch alice -f
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
62d19fd..9dbdebc v1.0 -> alice/tags/v1.0
```
diff --git a/crates/radicle-cli/examples/jj-init-bare.md b/crates/radicle-cli/examples/jj-init-bare.md
index 2832a20347..3a7029c4ac 100644
--- a/crates/radicle-cli/examples/jj-init-bare.md
+++ b/crates/radicle-cli/examples/jj-init-bare.md
@@ -12,5 +12,5 @@ $ cd heartwood.jj
```
$ rad .
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
diff --git a/crates/radicle-cli/examples/rad-block.md b/crates/radicle-cli/examples/rad-block.md
index 71ef29028f..c9503b092b 100644
--- a/crates/radicle-cli/examples/rad-block.md
+++ b/crates/radicle-cli/examples/rad-block.md
@@ -4,8 +4,8 @@ repositories from being seeded.
For instance, if our default policy is to seed, any unknown repository will
have its policy set to allow seeding:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --policy
-Repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji is being seeded with scope `all`
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --policy
+Repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G is being seeded with scope `all`
```
Since there is no policy specific to this repository, there's nothing to be
@@ -20,15 +20,15 @@ But if we wanted to prevent this repository from being seeded, while
allowing all other repositories, we could use `rad block`:
```
-$ rad block rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji set to 'block'
+$ rad block rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Policy for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G set to 'block'
```
We can see that it is now no longer seeded:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --policy
-Repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji is not being seeded
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --policy
+Repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G is not being seeded
```
And a 'block' policy was added:
@@ -38,15 +38,15 @@ $ rad seed
╭──────────────────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├──────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji Error determining name. block │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G Error determining name. block │
╰──────────────────────────────────────────────────────────────────────────────╯
```
If we want to reverse the blocking of the RID we can use `rad unblock`:
```
-$ rad unblock rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ The 'block' policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji is removed
+$ rad unblock rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ The 'block' policy for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G is removed
```
```
diff --git a/crates/radicle-cli/examples/rad-checkout-repo-config-linux.md b/crates/radicle-cli/examples/rad-checkout-repo-config-linux.md
index ace75c511e..1bf1c01c8f 100644
--- a/crates/radicle-cli/examples/rad-checkout-repo-config-linux.md
+++ b/crates/radicle-cli/examples/rad-checkout-repo-config-linux.md
@@ -14,10 +14,10 @@ $ cat .git/config
[push]
default = upstream
[remote "rad"]
- url = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+ url = rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
fetch = +refs/heads/*:refs/remotes/rad/*
fetch = +refs/tags/*:refs/remotes/rad/tags/*
- pushurl = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ pushurl = rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
[branch "master"]
remote = rad
merge = refs/heads/master
diff --git a/crates/radicle-cli/examples/rad-checkout-repo-config-macos.md b/crates/radicle-cli/examples/rad-checkout-repo-config-macos.md
index ff7bc1f3c4..9ee905e29d 100644
--- a/crates/radicle-cli/examples/rad-checkout-repo-config-macos.md
+++ b/crates/radicle-cli/examples/rad-checkout-repo-config-macos.md
@@ -16,10 +16,10 @@ $ cat .git/config
[push]
default = upstream
[remote "rad"]
- url = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+ url = rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
fetch = +refs/heads/*:refs/remotes/rad/*
fetch = +refs/tags/*:refs/remotes/rad/tags/*
- pushurl = rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ pushurl = rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
[branch "master"]
remote = rad
merge = refs/heads/master
diff --git a/crates/radicle-cli/examples/rad-checkout.md b/crates/radicle-cli/examples/rad-checkout.md
index e51b4199ce..6a2731c6dd 100644
--- a/crates/radicle-cli/examples/rad-checkout.md
+++ b/crates/radicle-cli/examples/rad-checkout.md
@@ -2,7 +2,7 @@ With the `rad checkout` command, you can create a new working copy from an
existing project.
```
-$ rad checkout rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad checkout rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
✓ Repository checkout successful under ./heartwood
```
@@ -32,8 +32,8 @@ Check the remote configuration:
```
$ git remote --verbose
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji (fetch)
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G (fetch)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
```
List the branches:
diff --git a/crates/radicle-cli/examples/rad-clean.md b/crates/radicle-cli/examples/rad-clean.md
index 7b6b9ae8cf..7387d33f2d 100644
--- a/crates/radicle-cli/examples/rad-clean.md
+++ b/crates/radicle-cli/examples/rad-clean.md
@@ -10,7 +10,7 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -18,23 +18,23 @@ Let's also inspect what remotes are in the repository:
``` ~alice
$ rad inspect --sigrefs
-z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 55be80540a7e9f10478fbc846913f2a6a19abe1d parent
-z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk e9f48ef90fe8592e1b1c95f96c21a59ca1495300 parent
+z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 65ca22ed02601b9cd3e65486fd871683d415a3ac parent
+z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk 954186394ad704149d952368f55aa7e270c09378 parent
```
Now let's clean the `heartwood` project:
``` ~alice
-$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
+$ rad clean rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-confirm
Removed z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-✓ Successfully cleaned rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+✓ Successfully cleaned rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
Inspecting the remotes again, we see that Bob is now gone:
``` ~alice
$ rad inspect --sigrefs
-z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 55be80540a7e9f10478fbc846913f2a6a19abe1d parent
+z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 65ca22ed02601b9cd3e65486fd871683d415a3ac parent
```
Note that Bob will be fetched again if we do not untrack his
@@ -45,23 +45,23 @@ Cleaning a repository again will remove no remotes, since we're
already at the minimal set of remotes:
``` ~alice
-$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
-✓ Successfully cleaned rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad clean rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-confirm
+✓ Successfully cleaned rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
Since Eve did not fork the repository, and has no refs of their own,
when they run `rad clean` it will remove the project entirely:
``` ~eve
-$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
+$ rad clean rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-confirm
Removed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-✓ Successfully cleaned rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+✓ Successfully cleaned rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
And attempting to clean the repository again, or any nonexistent
repository, has no effect on the storage at all:
``` ~eve (fail)
-$ rad clean rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
-✗ Error: repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji was not found
+$ rad clean rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-confirm
+✗ Error: repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G was not found
```
diff --git a/crates/radicle-cli/examples/rad-clone-all.md b/crates/radicle-cli/examples/rad-clone-all.md
index 48bf731ec7..83b697bcf3 100644
--- a/crates/radicle-cli/examples/rad-clone-all.md
+++ b/crates/radicle-cli/examples/rad-clone-all.md
@@ -1,7 +1,7 @@
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope all
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope all
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'all'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -32,7 +32,7 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── [...]
+ │ └── [..]
├── heads
│ └── master
└── rad
@@ -64,7 +64,7 @@ We can also create our own fork just by pushing:
``` (stderr)
$ git push -o no-sync rad master
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
* [new branch] master -> master
```
```
@@ -73,7 +73,7 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── [...]
+ │ └── [..]
├── heads
│ └── master
└── rad
diff --git a/crates/radicle-cli/examples/rad-clone-bare.md b/crates/radicle-cli/examples/rad-clone-bare.md
index fc645ae4dd..380a58c0c7 100644
--- a/crates/radicle-cli/examples/rad-clone-bare.md
+++ b/crates/radicle-cli/examples/rad-clone-bare.md
@@ -2,9 +2,9 @@ To create a local bare copy of a repository on the Radicle network, we use the
`clone` command, followed by the identifier or *RID* of the repository:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed --bare
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found [..] potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed --bare
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found [..] potential seed(s).
✓ Target met: [..] seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -53,10 +53,10 @@ We can also take a look at the remotes:
```
$ git remote -v
-alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
-alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji (fetch)
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
+alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
+alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G (fetch)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
```
Let's check the last commit!
@@ -76,6 +76,6 @@ $ rad ls --seeded
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-clone-connect.md b/crates/radicle-cli/examples/rad-clone-connect.md
index f6566a1b1f..624bf06d3a 100644
--- a/crates/radicle-cli/examples/rad-clone-connect.md
+++ b/crates/radicle-cli/examples/rad-clone-connect.md
@@ -2,9 +2,9 @@ If we're not connecting to seed nodes when cloning, the `clone` command will
automatically connect to the necessary seeds.
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
diff --git a/crates/radicle-cli/examples/rad-clone-directory.md b/crates/radicle-cli/examples/rad-clone-directory.md
index 93a21b2512..7c3eb15428 100644
--- a/crates/radicle-cli/examples/rad-clone-directory.md
+++ b/crates/radicle-cli/examples/rad-clone-directory.md
@@ -2,9 +2,9 @@ We can specify where a repository gets cloned into on our filesystem
by specifying the directory in the `rad clone` command:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed Developer/Radicle
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed Developer/Radicle
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./Developer/Radicle..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -22,8 +22,8 @@ Note that attempting to clone into a directory that already exists,
and is not empty, will fail:
``` (fail)
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed Developer/Radicle
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed Developer/Radicle
✗ Error: refusing to checkout repository to Developer/Radicle, since it already exists
-✗ Hint: try `rad checkout rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji` in a new directory
-✗ Error: failed to clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+✗ Hint: try `rad checkout rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G` in a new directory
+✗ Error: failed to clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
diff --git a/crates/radicle-cli/examples/rad-clone-partial-fail.md b/crates/radicle-cli/examples/rad-clone-partial-fail.md
index 44e6ec380a..cc41d7af00 100644
--- a/crates/radicle-cli/examples/rad-clone-partial-fail.md
+++ b/crates/radicle-cli/examples/rad-clone-partial-fail.md
@@ -5,9 +5,9 @@ $ rad node routing
╭──────────────────────────────────────────────────────────────────────────────────────╮
│ RID NID │
├──────────────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT │
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
╰──────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -15,9 +15,9 @@ When she tries to clone, one of those will fail to fetch. But the clone command
still returns successfully.
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --timeout 3s
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 3 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --timeout 3s
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 3 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
diff --git a/crates/radicle-cli/examples/rad-clone-scope.md b/crates/radicle-cli/examples/rad-clone-scope.md
index 4a56e6f13c..4dc789dc9c 100644
--- a/crates/radicle-cli/examples/rad-clone-scope.md
+++ b/crates/radicle-cli/examples/rad-clone-scope.md
@@ -1,8 +1,8 @@
By default `rad clone` should add a seeding policy with the `followed` scope:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
✓ Creating checkout in ./heartwood..
✓ Repository successfully cloned under [..]/heartwood/
╭────────────────────────────────────╮
@@ -15,7 +15,7 @@ $ rad seed
╭───────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├───────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji heartwood allow followed │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G heartwood allow followed │
╰───────────────────────────────────────────────────────────────────╯
$ rm -rf heartwood
```
@@ -23,8 +23,8 @@ $ rm -rf heartwood
Specifying a different scope explicitly should update the policy:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope all
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all'
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope all
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'all'
✓ Creating checkout in ./heartwood..
✓ Repository successfully cloned under [..]/heartwood/
╭────────────────────────────────────╮
@@ -37,7 +37,7 @@ $ rad seed
╭────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji heartwood allow all │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G heartwood allow all │
╰────────────────────────────────────────────────────────────────╯
$ rm -rf heartwood
```
@@ -45,7 +45,7 @@ $ rm -rf heartwood
Running `rad clone` again without an explicit scope parameter should not change the existing policy:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
✓ Creating checkout in ./heartwood..
✓ Repository successfully cloned under [..]/heartwood/
╭────────────────────────────────────╮
@@ -58,6 +58,6 @@ $ rad seed
╭────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji heartwood allow all │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G heartwood allow all │
╰────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-clone.md b/crates/radicle-cli/examples/rad-clone.md
index 55bf87e47b..cfee169be5 100644
--- a/crates/radicle-cli/examples/rad-clone.md
+++ b/crates/radicle-cli/examples/rad-clone.md
@@ -2,9 +2,9 @@ To create a local copy of a repository on the Radicle network, we use the
`clone` command, followed by the identifier or *RID* of the repository:
```
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found [..] potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found [..] potential seed(s).
✓ Target met: [..] seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -47,10 +47,10 @@ We can also take a look at the remotes:
```
$ git remote -v
-alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
-alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji (fetch)
-rad rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
+alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (fetch)
+alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (push)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G (fetch)
+rad rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (push)
```
Let's check the last commit!
@@ -70,6 +70,6 @@ $ rad ls --seeded
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-cob-log.md b/crates/radicle-cli/examples/rad-cob-log.md
index 29fb48bcc1..b53fdab881 100644
--- a/crates/radicle-cli/examples/rad-cob-log.md
+++ b/crates/radicle-cli/examples/rad-cob-log.md
@@ -6,7 +6,7 @@ First create an issue.
$ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue d87dcfe8c2b3200e78b128d9b959cfdf7063fefe │
+│ Issue cb9d9788d1854a6d4bc7235756df33b9d372a605 │
│ Author alice (you) │
│ Status open │
│ │
@@ -21,7 +21,7 @@ $ rad issue list
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├──────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) now │
+│ ● cb9d978 flux capacitor underpowered alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -45,25 +45,25 @@ $ rad patch
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● aa45913 Define power requirements alice (you) - 3e674d1 +0 -0 now │
+│ ● 26ba061 Define power requirements alice (you) - 3e674d1 +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
```
Both issue and patch COBs can be listed.
```
-$ rad cob list --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue
-d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-$ rad cob list --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch
-aa45913e757cacd46972733bddee5472c78fa32a
+$ rad cob list --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue
+cb9d9788d1854a6d4bc7235756df33b9d372a605
+$ rad cob list --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch
+26ba0615c6e911344ee61d53241a2903c5bf8623
```
We can look at the issue COB.
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-commit d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605
+commit cb9d9788d1854a6d4bc7235756df33b9d372a605
+resource 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -82,9 +82,9 @@ date Thu, 15 Dec 2022 17:28:04 +0000
We can look at the patch COB too.
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch --object aa45913e757cacd46972733bddee5472c78fa32a
-commit aa45913e757cacd46972733bddee5472c78fa32a
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch --object 26ba0615c6e911344ee61d53241a2903c5bf8623
+commit 26ba0615c6e911344ee61d53241a2903c5bf8623
+resource 86399084097fb674569f5bc5847da609ab91aa9f
rel 3e674d1a1df90807e934f9ae5da2591dd6848a33
rel f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -108,11 +108,11 @@ date Thu, 15 Dec 2022 17:28:04 +0000
Finally let's updated the issue and see the `parent` header:
```
-$ rad issue label d87dcfe --add bug --no-announce
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-commit abec0a9f3c945594c4e78d24d8ec679e56b22b79
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+$ rad issue label cb9d978 --add bug --no-announce
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605
+commit 3f72d4fdc26f02f64d67ae37f3f363634673b1ea
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent cb9d9788d1854a6d4bc7235756df33b9d372a605
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -123,8 +123,8 @@ date Thu, 15 Dec 2022 17:28:04 +0000
]
}
-commit d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+commit cb9d9788d1854a6d4bc7235756df33b9d372a605
+resource 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
diff --git a/crates/radicle-cli/examples/rad-cob-multiset.md b/crates/radicle-cli/examples/rad-cob-multiset.md
index bd52803a1e..808dc9ca92 100644
--- a/crates/radicle-cli/examples/rad-cob-multiset.md
+++ b/crates/radicle-cli/examples/rad-cob-multiset.md
@@ -41,28 +41,28 @@ It reads the current state of the grocery list and operations containing actions
We do not invoke the program directly, but instead use `rad cob create`:
```
-$ rad cob create --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type com.example.multiset --message "Create grocery shopping multiset" groceries.jsonl
+$ rad cob create --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type com.example.multiset --message "Create grocery shopping multiset" groceries.jsonl
9bba8e6f83ef56b11151ef6ad02cc4595f982aab
```
We can verify that the COB evaluated as expected:
```
-$ rad cob show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab
+$ rad cob show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab
{"jelly":0,"peanut butter":1,"salad":2}
```
To apply actions to COBs that already exist, we can use `rad cob update`:
```
-$ rad cob update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab --message "Modify grocery shopping multiset" groceries.jsonl
+$ rad cob update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab --message "Modify grocery shopping multiset" groceries.jsonl
d36aac77be13c1ca80edbfe7b7bf9b42c723f019
```
Again, we verify the result with `rad cob show`:
```
-$ rad cob show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab
+$ rad cob show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type com.example.multiset --object 9bba8e6f83ef56b11151ef6ad02cc4595f982aab
{"jelly":0,"peanut butter":2,"salad":4}
```
diff --git a/crates/radicle-cli/examples/rad-cob-operations.md b/crates/radicle-cli/examples/rad-cob-operations.md
index 53c31e03bb..58f3596f2f 100644
--- a/crates/radicle-cli/examples/rad-cob-operations.md
+++ b/crates/radicle-cli/examples/rad-cob-operations.md
@@ -7,28 +7,28 @@ To demonstrate, we will first create an issue and interact with it:
$ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue d87dcfe8c2b3200e78b128d9b959cfdf7063fefe │
+│ Issue cb9d9788d1854a6d4bc7235756df33b9d372a605 │
│ Author alice (you) │
│ Status open │
│ │
│ Flux capacitor power requirements exceed current supply │
╰─────────────────────────────────────────────────────────╯
-$ rad issue react d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --to d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --emoji ✨ --no-announce
-$ rad issue comment d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --message "Max power!" --no-announce
+$ rad issue react cb9d9788d1854a6d4bc7235756df33b9d372a605 --to cb9d9788d1854a6d4bc7235756df33b9d372a605 --emoji ✨ --no-announce
+$ rad issue comment cb9d9788d1854a6d4bc7235756df33b9d372a605 --message "Max power!" --no-announce
╭─────────────────────────╮
-│ alice (you) now 3c849c9 │
+│ alice (you) now 1ed4053 │
│ Max power! │
╰─────────────────────────╯
-$ rad issue assign d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --add did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-announce
+$ rad issue assign cb9d9788d1854a6d4bc7235756df33b9d372a605 --add did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-announce
```
Now, let's see the list of operations using `rad cob log`:
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-commit 376ba71113603004eae3c1b125c58cdc41d36b73
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605
+commit eef906e4c5174f987c250e3e7813775b76f222b2
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -39,33 +39,33 @@ date Thu, 15 Dec 2022 17:28:04 +0000
]
}
-commit 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 256908937f3cda8df522d5a3ba442eb935c3f11b
+commit 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent b9ec03b484bf82e857f82fa7fb1b510b371285d1
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment",
"body": "Max power!",
- "replyTo": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe"
+ "replyTo": "cb9d9788d1854a6d4bc7235756df33b9d372a605"
}
-commit 256908937f3cda8df522d5a3ba442eb935c3f11b
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+commit b9ec03b484bf82e857f82fa7fb1b510b371285d1
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent cb9d9788d1854a6d4bc7235756df33b9d372a605
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment.react",
- "id": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe",
+ "id": "cb9d9788d1854a6d4bc7235756df33b9d372a605",
"reaction": "✨",
"active": true
}
-commit d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+commit cb9d9788d1854a6d4bc7235756df33b9d372a605
+resource 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -86,10 +86,10 @@ options. We will need some commit revisions to use for those options, so let's
look at what those revision are by using `rad cob log`:
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-commit 376ba71113603004eae3c1b125c58cdc41d36b73
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605
+commit eef906e4c5174f987c250e3e7813775b76f222b2
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -100,33 +100,33 @@ date Thu, 15 Dec 2022 17:28:04 +0000
]
}
-commit 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 256908937f3cda8df522d5a3ba442eb935c3f11b
+commit 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent b9ec03b484bf82e857f82fa7fb1b510b371285d1
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment",
"body": "Max power!",
- "replyTo": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe"
+ "replyTo": "cb9d9788d1854a6d4bc7235756df33b9d372a605"
}
-commit 256908937f3cda8df522d5a3ba442eb935c3f11b
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+commit b9ec03b484bf82e857f82fa7fb1b510b371285d1
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent cb9d9788d1854a6d4bc7235756df33b9d372a605
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment.react",
- "id": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe",
+ "id": "cb9d9788d1854a6d4bc7235756df33b9d372a605",
"reaction": "✨",
"active": true
}
-commit d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+commit cb9d9788d1854a6d4bc7235756df33b9d372a605
+resource 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -146,10 +146,10 @@ If we provide only the `--from` option, the operations we get back start from th
revision and go until the end:
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --from 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-commit 376ba71113603004eae3c1b125c58cdc41d36b73
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605 --from 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+commit eef906e4c5174f987c250e3e7813775b76f222b2
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -160,16 +160,16 @@ date Thu, 15 Dec 2022 17:28:04 +0000
]
}
-commit 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 256908937f3cda8df522d5a3ba442eb935c3f11b
+commit 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent b9ec03b484bf82e857f82fa7fb1b510b371285d1
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment",
"body": "Max power!",
- "replyTo": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe"
+ "replyTo": "cb9d9788d1854a6d4bc7235756df33b9d372a605"
}
```
@@ -178,22 +178,22 @@ Conversely, if we provide only the `--until` option, the operations we get back
start from the beginning and stop at that revision:
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --until 256908937f3cda8df522d5a3ba442eb935c3f11b
-commit 256908937f3cda8df522d5a3ba442eb935c3f11b
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605 --until b9ec03b484bf82e857f82fa7fb1b510b371285d1
+commit b9ec03b484bf82e857f82fa7fb1b510b371285d1
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent cb9d9788d1854a6d4bc7235756df33b9d372a605
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment.react",
- "id": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe",
+ "id": "cb9d9788d1854a6d4bc7235756df33b9d372a605",
"reaction": "✨",
"active": true
}
-commit d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
+commit cb9d9788d1854a6d4bc7235756df33b9d372a605
+resource 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -212,28 +212,28 @@ date Thu, 15 Dec 2022 17:28:04 +0000
Finally, if we provide both, we get back that exact range:
```
-$ rad cob log --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --from 256908937f3cda8df522d5a3ba442eb935c3f11b --until 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-commit 3c849c9b555b18be9a1f6c71fb254ba000de8cfe
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent 256908937f3cda8df522d5a3ba442eb935c3f11b
+$ rad cob log --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object cb9d9788d1854a6d4bc7235756df33b9d372a605 --from b9ec03b484bf82e857f82fa7fb1b510b371285d1 --until 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+commit 1ed40536d39ace98070e97a2ab0e39aabe91a9b8
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent b9ec03b484bf82e857f82fa7fb1b510b371285d1
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment",
"body": "Max power!",
- "replyTo": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe"
+ "replyTo": "cb9d9788d1854a6d4bc7235756df33b9d372a605"
}
-commit 256908937f3cda8df522d5a3ba442eb935c3f11b
-resource 0656c217f917c3e06234771e9ecae53aba5e173e
-parent d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+commit b9ec03b484bf82e857f82fa7fb1b510b371285d1
+resource 86399084097fb674569f5bc5847da609ab91aa9f
+parent cb9d9788d1854a6d4bc7235756df33b9d372a605
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "comment.react",
- "id": "d87dcfe8c2b3200e78b128d9b959cfdf7063fefe",
+ "id": "cb9d9788d1854a6d4bc7235756df33b9d372a605",
"reaction": "✨",
"active": true
}
diff --git a/crates/radicle-cli/examples/rad-cob-show.md b/crates/radicle-cli/examples/rad-cob-show.md
index f5d0420db4..10e265f8ed 100644
--- a/crates/radicle-cli/examples/rad-cob-show.md
+++ b/crates/radicle-cli/examples/rad-cob-show.md
@@ -9,7 +9,7 @@ First create an issue.
$ rad issue open --title "spice harvester broken" --description "Fremen have attacked, maybe we went too far?" --no-announce
╭──────────────────────────────────────────────────╮
│ Title spice harvester broken │
-│ Issue 9de644864342d7a505eb8d58d1ef20e5bb05de2e │
+│ Issue 284179861d9b0481bb32d1b23a433f649e721cd1 │
│ Author alice (you) │
│ Status open │
│ │
@@ -24,7 +24,7 @@ $ rad issue list
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├─────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 9de6448 spice harvester broken alice (you) now │
+│ ● 2841798 spice harvester broken alice (you) now │
╰─────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -48,37 +48,37 @@ $ rad patch
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d1f7f86 Start drafting peace treaty alice (you) - 575ed68 +0 -0 now │
+│ ● 62cf30d Start drafting peace treaty alice (you) - 575ed68 +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
```
Both issue and patch COBs can be listed.
```
-$ rad cob list --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue
-9de644864342d7a505eb8d58d1ef20e5bb05de2e
-$ rad cob list --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch
-d1f7f869fde9fac19c1779c4c2e77e8361333f91
+$ rad cob list --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue
+284179861d9b0481bb32d1b23a433f649e721cd1
+$ rad cob list --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch
+62cf30dfdbb24063abb46c71dbf230aeb0a6c930
```
We can show the issue COB.
```
-$ rad cob show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object 9de644864342d7a505eb8d58d1ef20e5bb05de2e
-{"assignees":[],"title":"spice harvester broken","state":{"status":"open"},"labels":[],"thread":{"comments":{"9de644864342d7a505eb8d58d1ef20e5bb05de2e":{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","reactions":[],"resolved":false,"body":"Fremen have attacked, maybe we went too far?","edits":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"Fremen have attacked, maybe we went too far?","embeds":[]}]}},"timeline":["9de644864342d7a505eb8d58d1ef20e5bb05de2e"]}}
+$ rad cob show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object 284179861d9b0481bb32d1b23a433f649e721cd1
+{"assignees":[],"title":"spice harvester broken","state":{"status":"open"},"labels":[],"thread":{"comments":{"284179861d9b0481bb32d1b23a433f649e721cd1":{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","reactions":[],"resolved":false,"body":"Fremen have attacked, maybe we went too far?","edits":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"Fremen have attacked, maybe we went too far?","embeds":[]}]}},"timeline":["284179861d9b0481bb32d1b23a433f649e721cd1"]}}
```
We can show the patch COB too.
```
-$ rad cob show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch --object d1f7f869fde9fac19c1779c4c2e77e8361333f91
-{"title":"Start drafting peace treaty","author":{"id":"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"},"state":{"status":"open"},"target":"delegates","labels":[],"merges":{},"revisions":{"d1f7f869fde9fac19c1779c4c2e77e8361333f91":{"id":"d1f7f869fde9fac19c1779c4c2e77e8361333f91","author":{"id":"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"},"description":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"See details.","embeds":[]}],"base":"f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354","oid":"575ed68c716d6aae81ea6b718fd9ac66a8eae532","discussion":{"comments":{},"timeline":[]},"reviews":{},"timestamp":1671125284000,"resolves":[],"reactions":[]}},"assignees":[],"timeline":["d1f7f869fde9fac19c1779c4c2e77e8361333f91"],"reviews":{}}
+$ rad cob show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch --object 62cf30dfdbb24063abb46c71dbf230aeb0a6c930
+{"title":"Start drafting peace treaty","author":{"id":"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"},"state":{"status":"open"},"target":"delegates","labels":[],"merges":{},"revisions":{"62cf30dfdbb24063abb46c71dbf230aeb0a6c930":{"id":"62cf30dfdbb24063abb46c71dbf230aeb0a6c930","author":{"id":"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"},"description":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"See details.","embeds":[]}],"base":"f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354","oid":"575ed68c716d6aae81ea6b718fd9ac66a8eae532","discussion":{"comments":{},"timeline":[]},"reviews":{},"timestamp":1671125284000,"resolves":[],"reactions":[]}},"assignees":[],"timeline":["62cf30dfdbb24063abb46c71dbf230aeb0a6c930"],"reviews":{}}
```
Finally let's update the issue and see the output of `rad cob show` also changes.
```
-$ rad issue label 9de6448 --add bug --no-announce
-$ rad cob show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.issue --object 9de644864342d7a505eb8d58d1ef20e5bb05de2e
-{"assignees":[],"title":"spice harvester broken","state":{"status":"open"},"labels":["bug"],"thread":{"comments":{"9de644864342d7a505eb8d58d1ef20e5bb05de2e":{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","reactions":[],"resolved":false,"body":"Fremen have attacked, maybe we went too far?","edits":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"Fremen have attacked, maybe we went too far?","embeds":[]}]}},"timeline":["9de644864342d7a505eb8d58d1ef20e5bb05de2e"]}}
+$ rad issue label 2841798 --add bug --no-announce
+$ rad cob show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.issue --object 284179861d9b0481bb32d1b23a433f649e721cd1
+{"assignees":[],"title":"spice harvester broken","state":{"status":"open"},"labels":["bug"],"thread":{"comments":{"284179861d9b0481bb32d1b23a433f649e721cd1":{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","reactions":[],"resolved":false,"body":"Fremen have attacked, maybe we went too far?","edits":[{"author":"z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi","timestamp":1671125284000,"body":"Fremen have attacked, maybe we went too far?","embeds":[]}]}},"timeline":["284179861d9b0481bb32d1b23a433f649e721cd1"]}}
```
diff --git a/crates/radicle-cli/examples/rad-cob-update-identity.md b/crates/radicle-cli/examples/rad-cob-update-identity.md
index 40083e8c22..0259ca911b 100644
--- a/crates/radicle-cli/examples/rad-cob-update-identity.md
+++ b/crates/radicle-cli/examples/rad-cob-update-identity.md
@@ -1,6 +1,6 @@
Updating the repository identity via `rad cob update` is forbidden:
``` (fail)
-$ rad cob update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.id --object 0656c217f917c3e06234771e9ecae53aba5e173e --message "Danger" /dev/null
+$ rad cob update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.id --object 86399084097fb674569f5bc5847da609ab91aa9f --message "Danger" /dev/null
✗ Error: Update of collaborative objects of type xyz.radicle.id is not supported.
```
\ No newline at end of file
diff --git a/crates/radicle-cli/examples/rad-cob-update.md b/crates/radicle-cli/examples/rad-cob-update.md
index efd6682b8f..c571ddedd5 100644
--- a/crates/radicle-cli/examples/rad-cob-update.md
+++ b/crates/radicle-cli/examples/rad-cob-update.md
@@ -12,8 +12,8 @@ $ git commit --message "Add README, just for the fun"
``` (stderr)
$ git push rad -o patch.message="Add README, just for the fun" HEAD:refs/patches
-✓ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -28,25 +28,25 @@ $ git commit -v -m "Define the LICENSE"
``` (stderr)
$ git push -f -o patch.message="Add License"
-✓ Patch 89f7afb updated to revision 5d78dd5376453e25df5988ec86951c99cb73742c
-To compare against your previous revision 89f7afb, run:
+✓ Patch f36ce41 updated to revision 66230c3d87c5c444803e7d012a710013505dcdb9
+To compare against your previous revision f36ce41, run:
git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 03c02af4b12a593d17a06d38fae50a57fc3c339a 8945f6189adf027892c85ac57f7e9341049c2537
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 03c02af..8945f61 changes -> patches/89f7afb1511b976482b21f6b2f39aef7f4fb88a2
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 03c02af..8945f61 changes -> patches/f36ce41ee8d55d3723ad65ad39741391f9bed979
```
Let's look at the patch, to see what it looks like before editing it:
```
-$ rad patch show 89f7afb
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add README, just for the fun │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches changes │
│ Commits ahead 2, behind 0 │
@@ -55,8 +55,8 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ f2de534..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ f2de534..8945f61 by alice (you) now │
+│ ● Revision f36ce41 @ f2de534..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ f2de534..8945f61 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -64,14 +64,14 @@ We can change the title and description of the patch itself by using a
multi-line message (using two `--message` options here):
```
-$ rad patch edit 89f7afb --message "Add Metadata" --message "Add README & LICENSE" --no-announce
-$ rad patch show 89f7afb
+$ rad patch edit f36ce41 --message "Add Metadata" --message "Add README & LICENSE" --no-announce
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add Metadata │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches changes │
│ Commits ahead 2, behind 0 │
@@ -82,15 +82,15 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ f2de534..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ f2de534..8945f61 by alice (you) now │
+│ ● Revision f36ce41 @ f2de534..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ f2de534..8945f61 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
We prepare the file `revision-edit.json` which contains one action (thus one line) to be applied.
``` ./revision-edit.jsonl
-{"type": "revision.edit", "description": "Add README and LICENSE", "revision": "89f7afb1511b976482b21f6b2f39aef7f4fb88a2"}
+{"type": "revision.edit", "description": "Add README and LICENSE", "revision": "f36ce41ee8d55d3723ad65ad39741391f9bed979"}
```
We now use `rad cob update` to edit the patch another time, rewriting the description.
@@ -99,12 +99,12 @@ specifying the revision for which the description should be changed, and `descri
specifying the new description.
```
-$ rad cob update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch --object 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 --message "Edit patch" revision-edit.jsonl
-79b816e92735c49b33d93a31890fdf040b36234c
-$ rad patch show --verbose 89f7afb
+$ rad cob update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch --object f36ce41ee8d55d3723ad65ad39741391f9bed979 --message "Edit patch" revision-edit.jsonl
+bf3e9bdd3778836be49b76f987d15066b973952e
+$ rad patch show --verbose f36ce41
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Add Metadata │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -118,8 +118,8 @@ $ rad patch show --verbose 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..03c02af4b12a593d17a06d38fae50a57fc3c339a by alice (you) now │
-│ ↑ Revision 5d78dd5376453e25df5988ec86951c99cb73742c with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..8945f6189adf027892c85ac57f7e9341049c2537 by alice (you) now │
+│ ● Revision f36ce41ee8d55d3723ad65ad39741391f9bed979 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..03c02af4b12a593d17a06d38fae50a57fc3c339a by alice (you) now │
+│ ↑ Revision 66230c3d87c5c444803e7d012a710013505dcdb9 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..8945f6189adf027892c85ac57f7e9341049c2537 by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -142,7 +142,7 @@ We prepare the file `revision-create.jsonl` which contains one action.
Attempting to create the new revision right away would fail:
``` (fail)
-$ rad cob update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch --object 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 --message "Create new revision" revision.jsonl
+$ rad cob update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch --object f36ce41ee8d55d3723ad65ad39741391f9bed979 --message "Create new revision" revision.jsonl
✗ Error: store: update error: failed to read 'f1339dd109e538c6b3a7fed3e72403e1b4db08c9' from git odb
```
@@ -158,15 +158,15 @@ $ git push rad :tmp/heads/f1339dd109e538c6b3a7fed3e72403e1b4db08c9
Now we can invoke `rad cob update`:
```
-$ rad cob update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --type xyz.radicle.patch --object 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 --message "Create new revision" revision.jsonl
-2da9c025a1d14d93c4f2cec60a7878afbc5e2a3c
-$ rad patch show 89f7afb
+$ rad cob update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --type xyz.radicle.patch --object f36ce41ee8d55d3723ad65ad39741391f9bed979 --message "Create new revision" revision.jsonl
+fdfc4def2abbd93059a6fbf48276dc91c0d49636
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add Metadata │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head f1339dd109e538c6b3a7fed3e72403e1b4db08c9 │
-│ Base [.. ] │
+│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
│ Target master │
│ Branches changes │
│ Commits ahead 3, behind 0 │
@@ -178,8 +178,8 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ f2de534..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ f2de534..8945f61 by alice (you) now │
-│ ↑ Revision 2da9c02 @ f2de534..f1339dd by alice (you) now │
+│ ● Revision f36ce41 @ f2de534..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ f2de534..8945f61 by alice (you) now │
+│ ↑ Revision fdfc4de @ f2de534..f1339dd by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-fetch.md b/crates/radicle-cli/examples/rad-fetch.md
index 89a4dd783f..cf384e4be1 100644
--- a/crates/radicle-cli/examples/rad-fetch.md
+++ b/crates/radicle-cli/examples/rad-fetch.md
@@ -5,12 +5,12 @@ necessary.
Instead, we want to fetch the project from the network into our local
storage. In this scenario, we know that the project is
-`rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji`. In order to fetch it, we first
+`rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G`. In order to fetch it, we first
have to update our seeding policy for the project.
```
-$ rad seed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-fetch
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+$ rad seed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-fetch
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
```
Now that the project is seeding we can fetch it and we will have it in
@@ -18,8 +18,8 @@ our local storage. Note that the `seed` command can also be told to fetch
by passing the `--fetch` option.
```
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
diff --git a/crates/radicle-cli/examples/rad-fork.md b/crates/radicle-cli/examples/rad-fork.md
index 3fc0ff6379..30dee37650 100644
--- a/crates/radicle-cli/examples/rad-fork.md
+++ b/crates/radicle-cli/examples/rad-fork.md
@@ -4,12 +4,12 @@ NID. This is demonstrated below where our NID is
`z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk`:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --refs
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --refs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── [...]
+ │ └── [..]
├── heads
│ └── master
└── rad
@@ -22,20 +22,20 @@ To remedy this, we can use the `rad fork` command for the project we
wish to fork:
```
-$ rad fork rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Forked repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+$ rad fork rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Forked repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
```
Now, if we `rad inspect` the project's refs again we will see that we
have a copy of the main set of refs:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --refs
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --refs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── [...]
+ │ └── [..]
├── heads
│ └── master
└── rad
diff --git a/crates/radicle-cli/examples/rad-help.md b/crates/radicle-cli/examples/rad-help.md
index c25d2557bf..c034dc36cb 100644
--- a/crates/radicle-cli/examples/rad-help.md
+++ b/crates/radicle-cli/examples/rad-help.md
@@ -9,7 +9,7 @@ Do you have feedback?
- Mail <feedback@radicle.dev>
(Messages are automatically posted to the public #feedback channel on Zulip.)
-Usage: rad[EXE] <COMMAND>
+Usage: rad <COMMAND>
Commands:
auth Manage identities and profiles
diff --git a/crates/radicle-cli/examples/rad-id-collaboration.md b/crates/radicle-cli/examples/rad-id-collaboration.md
index f88738a65c..567e436014 100644
--- a/crates/radicle-cli/examples/rad-id-collaboration.md
+++ b/crates/radicle-cli/examples/rad-id-collaboration.md
@@ -7,10 +7,10 @@ First, we'll start off with Alice adding Bob. It's necessary for Bob
to have a fork of the project and Alice must be aware of the fork:
``` ~bob
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi
@@ -30,8 +30,8 @@ to the default branch, she must set the `threshold` to `2` when adding
Bob as a delegate:
``` ~alice (fails)
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
-✗ Error: failed to verify delegates for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
+✗ Error: failed to verify delegates for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
✗ Error: a threshold of 2 delegates cannot be met, found 1 delegate(s) and the following delegates are missing [did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk]
✗ Hint: run `rad follow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk` to follow this missing peer
✗ Hint: run `rad sync -f` to attempt to fetch the newly followed peers
@@ -50,15 +50,15 @@ So, instead Alice needs to first follow Bob and fetch his references:
$ rad follow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --alias bob
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 1 node(s)
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
-069e7d58faa9a7473d27f5510d676af33282796f
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
+c7d68a801ed8c107521cb63b4089b4bd6601fad4
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 3 node(s)
```
@@ -67,8 +67,8 @@ Bob can confirm that he was made a delegate by fetching the update:
``` ~bob
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 1 node(s)
$ rad inspect --delegates
@@ -81,10 +81,10 @@ project. For Bob to propose Eve, similar steps need to happen as
between Alice and Bob. Eve first needs to set up a fork:
``` ~eve
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSL…StBU8Vi
@@ -104,11 +104,11 @@ $ git push rad master
Bob then adds Eve as a delegate:
``` ~bob
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm -q
-3cd3c7f9900de0fcb19705856a7cc339a38fb0b3
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm -q
+46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 3 node(s)
```
@@ -122,27 +122,27 @@ the change to meet a quorum of votes (`votes >= (delegates / 2) + 1`):
``` ~alice
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
✓ Fetched repository from 2 seed(s)
✓ Nothing to announce, already in sync with 3 node(s) (see `rad sync status`)
$ rad id list
╭────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created │
├────────────────────────────────────────────────────────────────────────────────┤
-│ ● 3cd3c7f Add Eve bob z6Mkt67…v4N1tRk active now │
-│ ● 069e7d5 Add Bob alice (you) accepted now │
-│ ● 0656c21 Initial revision alice (you) accepted now │
+│ ● c7d68a8 Add Eve bob z6Mkt67…v4N1tRk active now │
+│ ● c7d68a8 Add Bob alice (you) accepted now │
+│ ● 8639908 Initial revision alice (you) accepted now │
╰────────────────────────────────────────────────────────────────────────────────╯
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --sigrefs
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --sigrefs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 6acd3b370839318d96dbfff43948bab2bcdd3681
z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk c40018821dc1b41cad75e91e0c9d00827e815324
-$ rad id accept 3cd3c7f
-✓ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 accepted
+$ rad id accept c7d68a8
+✓ Revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf accepted
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Eve │
-│ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 │
-│ Blob 74581605d1f75396c331487a10ca61c4815ed685 │
+│ Revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf │
+│ Blob 57dda7d9ab25ad958838e479c0c8e5ab7af56cd7 │
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State accepted │
│ Quorum yes │
@@ -157,11 +157,11 @@ since she has become a delegate:
``` ~alice
$ rad sync --timeout 3s
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 3 node(s)
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --sigrefs
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --sigrefs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 1f716870f890be0c13fdd0af9f527af849fec792 parent
z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk c40018821dc1b41cad75e91e0c9d00827e815324 parent
z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z 95cd447c57de8d232c6154f5dba0451aa593520e parent
@@ -173,8 +173,8 @@ see that both seeds are `synced`:
``` ~eve
$ rad sync
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkvVv…Z1Ct4tD@[..]..
-✓ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from z6MkuPZ…xEuaPUp@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkvVv…Z1Ct4tD@[..]..
+✓ Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from z6MkuPZ…xEuaPUp@[..]..
✓ Fetched repository from 2 seed(s)
✓ Synced with 3 node(s)
$ rad sync status
diff --git a/crates/radicle-cli/examples/rad-id-conflict.md b/crates/radicle-cli/examples/rad-id-conflict.md
index 32d1e7a9b0..26c65862ad 100644
--- a/crates/radicle-cli/examples/rad-id-conflict.md
+++ b/crates/radicle-cli/examples/rad-id-conflict.md
@@ -2,12 +2,12 @@ First let's add Bob as a delegate, and sync the changes to Bob:
``` ~alice
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --threshold 2 -q
-0ca42d376bd566631083c8913cf86bec722da392
+491c96a516cd9ed236f83e2e2d52d8799f31f4b4
```
``` ~bob
$ cd heartwood
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -17,11 +17,11 @@ time:
``` ~alice
$ rad id update --title "Edit project name" --description "" --payload "xyz.radicle.project" "name" '"heart"' -q
-12d7300d1bbba84e4e5760c8c61999bf5fefb81a
+3ed4e24714345d5a27563b671f219112db17d482
```
``` ~bob
$ rad id update --title "Edit project name" --description "" --payload "xyz.radicle.project" "name" '"wood"' -q
-89b2623e7f2ddf5748661b15b9975ab0b4ee17ab
+ff74fd6ae8df3729b4554e2287f403cb335ff615
```
When Alice syncs with Bob, she notices the problem: there are two active
@@ -29,18 +29,18 @@ revisions, and because she's created one of them she has implicitly voted
for it.
``` ~alice
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad id list
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created Parent │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 89b2623 Edit project name bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk active now 0ca42d3 │
-│ ● 12d7300 Edit project name alice (you) active now 0ca42d3 │
-│ ● 0ca42d3 Add Bob alice (you) accepted now 0656c21 │
-│ ● 0656c21 Initial revision alice (you) accepted now none │
+│ ● ff74fd6 Edit project name bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk active now 491c96a │
+│ ● 3ed4e24 Edit project name alice (you) active now 491c96a │
+│ ● 491c96a Add Bob alice (you) accepted now 8639908 │
+│ ● 8639908 Initial revision alice (you) accepted now none │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Hints:
@@ -48,12 +48,12 @@ Hints:
● accepted
● rejected:
✘ … by delegate votes ↥ … by parent ⇄ … by sibling
-$ rad id show 12d7300
+$ rad id show 3ed4e24
╭────────────────────────────────────────────────────────────────────────╮
│ Title Edit project name │
-│ Revision 12d7300d1bbba84e4e5760c8c61999bf5fefb81a │
-│ Parent 0ca42d376bd566631083c8913cf86bec722da392 │
-│ Blob e93aa3e3c5c448bacd3537a81daf1437eccd046a │
+│ Revision 3ed4e24714345d5a27563b671f219112db17d482 │
+│ Parent 491c96a516cd9ed236f83e2e2d52d8799f31f4b4 │
+│ Blob 86976266f9461d48203823b309d18866237af3c0 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │
│ Quorum no │
@@ -62,11 +62,22 @@ $ rad id show 12d7300
│ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,14 +1,14 @@
+@@ -1,24 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
- "name": "heartwood"
+ "name": "heart"
@@ -75,16 +86,15 @@ $ rad id show 12d7300
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 2
+ ]
}
```
If she tries to accept Bob's revision she'll receive an appropriate error:
``` ~alice (fail)
-$ rad id accept 89b2623
-✗ Error: apply failed: delegate already accepted a sibling revision '12d7300d1bbba84e4e5760c8c61999bf5fefb81a'
+$ rad id accept ff74fd6
+✗ Error: apply failed: delegate already accepted a sibling revision '3ed4e24714345d5a27563b671f219112db17d482'
```
However this isn't a problem as long as we don't try to accept both. Alice
@@ -92,15 +102,15 @@ decides to go with Bob's proposal, so she redacts her own first and then
accepts his:
``` ~alice
-$ rad id redact 12d7300 -q
-$ rad id accept 89b2623 -q
+$ rad id redact 3ed4e24 -q
+$ rad id accept ff74fd6 -q
$ rad id list
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created Parent │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 89b2623 Edit project name bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk accepted now 0ca42d3 │
-│ ● 0ca42d3 Add Bob alice (you) accepted now 0656c21 │
-│ ● 0656c21 Initial revision alice (you) accepted now none │
+│ ● ff74fd6 Edit project name bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk accepted now 491c96a │
+│ ● 491c96a Add Bob alice (you) accepted now 8639908 │
+│ ● 8639908 Initial revision alice (you) accepted now none │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Hints:
@@ -114,12 +124,12 @@ Alice's revision was redacted and is no longer visible. Bob syncs and sees
that the conflict is resolved:
``` ~bob
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
``` ~bob (fail)
-$ rad id show 12d7300
-✗ Error: revision `12d7300d1bbba84e4e5760c8c61999bf5fefb81a` not found
+$ rad id show 3ed4e24
+✗ Error: revision `3ed4e24714345d5a27563b671f219112db17d482` not found
```
diff --git a/crates/radicle-cli/examples/rad-id-migrate-vote.md b/crates/radicle-cli/examples/rad-id-migrate-vote.md
new file mode 100644
index 0000000000..9ff3f82403
--- /dev/null
+++ b/crates/radicle-cli/examples/rad-id-migrate-vote.md
@@ -0,0 +1,110 @@
+Alice adds Bob as a delegate. With two delegates, no revision is adopted until
+both have voted.
+
+``` ~alice
+$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --description "" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
+c036c0d89ce26aef3ad7da402157dba16b5163b4
+```
+
+Alice proposes the migration to identity document version 2. It waits for Bob.
+
+``` ~alice
+$ rad id migrate --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Migrate identity" --description "" --no-confirm
+Migrating identity document from version 1 to 2. Once adopted, this repository is no longer readable to older releases.
+✓ Identity revision 9cad7b4bc7a3180902ed5d2cc945d242cf8f4394 created
+╭────────────────────────────────────────────────────────────────────────╮
+│ Title Migrate identity │
+│ Revision 9cad7b4bc7a3180902ed5d2cc945d242cf8f4394 │
+│ Parent c036c0d89ce26aef3ad7da402157dba16b5163b4 │
+│ Blob 0653b9dbe278688862856d37e1c6bb66ef35ebed │
+│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
+│ State active │
+│ Quorum no │
+├────────────────────────────────────────────────────────────────────────┤
+│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
+│ ? did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
+╰────────────────────────────────────────────────────────────────────────╯
+
+@@ -1,14 +1,24 @@
+ {
++ "version": 2,
+ "payload": {
++ "xyz.radicle.crefs": {
++ "rules": {
++ "refs/heads/master": {
++ "allow": "delegates",
++ "threshold": 1
++ }
++ },
++ "symbolic": {
++ "HEAD": "refs/heads/master"
++ }
++ },
+ "xyz.radicle.project": {
+- "defaultBranch": "master",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": [
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
+- ],
+- "threshold": 1
++ ]
+ }
+```
+
+Bob fetches the proposal and accepts it. Voting on a revision whose parent is a
+version 1 document works the same as any other vote.
+
+``` ~bob
+$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+✓ Target met: 1 seed(s)
+🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+$ rad id accept 9cad7b4bc7a3180902ed5d2cc945d242cf8f4394 --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
+✓ Revision 9cad7b4bc7a3180902ed5d2cc945d242cf8f4394 accepted
+╭────────────────────────────────────────────────────────────────────────╮
+│ Title Migrate identity │
+│ Revision 9cad7b4bc7a3180902ed5d2cc945d242cf8f4394 │
+│ Parent c036c0d89ce26aef3ad7da402157dba16b5163b4 │
+│ Blob 0653b9dbe278688862856d37e1c6bb66ef35ebed │
+│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
+│ State accepted │
+│ Quorum yes │
+├────────────────────────────────────────────────────────────────────────┤
+│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice │
+│ ✓ did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob (you) │
+╰────────────────────────────────────────────────────────────────────────╯
+```
+
+The document is now at version 2 for both delegates.
+
+``` ~bob
+$ rad inspect --identity rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+{
+ "version": 2,
+ "payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
+ "xyz.radicle.project": {
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": [
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
+ ]
+}
+```
diff --git a/crates/radicle-cli/examples/rad-id-migrate.md b/crates/radicle-cli/examples/rad-id-migrate.md
new file mode 100644
index 0000000000..d28d90a623
--- /dev/null
+++ b/crates/radicle-cli/examples/rad-id-migrate.md
@@ -0,0 +1,181 @@
+A repository can be initialized at an older identity document version, so that
+it stays readable to releases that predate the current version.
+
+```
+$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --identity-version 1 --no-confirm --public
+
+Initializing public Radicle 👾 repository in [..]
+
+✓ Repository heartwood created.
+
+Your Repository ID (RID) is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+You can show it any time by running `rad .` from this directory.
+
+Your repository will be announced to the network when you start your node.
+You can start your node with `rad node start`.
+To push changes, run `git push`.
+```
+
+The document is stored in the version 1 format: the default branch lives in the
+`xyz.radicle.project` payload and the write quorum in the top-level `threshold`.
+
+```
+$ rad inspect --identity
+{
+ "payload": {
+ "xyz.radicle.project": {
+ "defaultBranch": "master",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": [
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ ],
+ "threshold": 1
+}
+```
+
+Readers see the document migrated to the current version, so the default branch
+and its quorum appear as a canonical reference rule even though they are not
+stored that way.
+
+```
+$ rad inspect --payload
+{
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
+ "xyz.radicle.project": {
+ "name": "heartwood",
+ "description": "Radicle Heartwood Protocol & Stack"
+ }
+}
+```
+
+Everything else works as usual against such a repository. Patches open and merge
+against the default branch the migrated view resolves.
+
+```
+$ rad inspect
+rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+```
+
+```
+$ git checkout -q -b flux-capacitor-power
+$ touch REQUIREMENTS
+$ git add REQUIREMENTS
+$ git commit -q -m "Define power requirements"
+```
+
+``` (stderr)
+$ git push rad -o patch.message="Define power requirements" HEAD:refs/patches
+✓ Patch b52d0f6358430655d7305f28a9f417cd5985dee3 opened
+To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ * [new reference] HEAD -> refs/patches
+```
+
+``` (stderr)
+$ git checkout -q master
+$ git merge -q flux-capacitor-power
+$ git push rad master
+✓ Patch b52d0f6358430655d7305f28a9f417cd5985dee3 merged
+✓ Canonical reference refs/heads/master updated to target commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
+To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f2de534..3e674d1 master -> master
+```
+
+When you are ready to move to the current version, propose the migration. As the
+only delegate, your own vote adopts it immediately.
+
+```
+$ rad id migrate --title "Migrate identity" --description "Move to version 2"
+Migrating identity document from version 1 to 2. Once adopted, this repository is no longer readable to older releases.
+✓ Identity revision 487a05d8fc17ace09103a4a20b43030353e0e943 created
+╭────────────────────────────────────────────────────────────────────────╮
+│ Title Migrate identity │
+│ Revision 487a05d8fc17ace09103a4a20b43030353e0e943 │
+│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
+│ Blob f10bd9e36848dc4eb70cc078d1d0bbaac7c1ba61 │
+│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
+│ State accepted │
+│ Quorum yes │
+│ │
+│ Move to version 2 │
+├────────────────────────────────────────────────────────────────────────┤
+│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
+╰────────────────────────────────────────────────────────────────────────╯
+
+@@ -1,13 +1,23 @@
+ {
++ "version": 2,
+ "payload": {
++ "xyz.radicle.crefs": {
++ "rules": {
++ "refs/heads/master": {
++ "allow": "delegates",
++ "threshold": 1
++ }
++ },
++ "symbolic": {
++ "HEAD": "refs/heads/master"
++ }
++ },
+ "xyz.radicle.project": {
+- "defaultBranch": "master",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": [
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+- ],
+- "threshold": 1
++ ]
+ }
+```
+
+The default branch and its quorum now live in the `xyz.radicle.crefs` payload,
+and the stored document and the migrated view are one and the same.
+
+```
+$ rad inspect --identity
+{
+ "version": 2,
+ "payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
+ "xyz.radicle.project": {
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": [
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ ]
+}
+```
+
+Migrating again has nothing to do.
+
+``` (fail)
+$ rad id migrate --title "Migrate identity" --description "Move to version 2"
+✗ Error: identity document is already at version 2
+```
diff --git a/crates/radicle-cli/examples/rad-id-multi-delegate.md b/crates/radicle-cli/examples/rad-id-multi-delegate.md
index 3827c50bc9..a430645bfa 100644
--- a/crates/radicle-cli/examples/rad-id-multi-delegate.md
+++ b/crates/radicle-cli/examples/rad-id-multi-delegate.md
@@ -1,24 +1,24 @@
``` ~alice
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
-069e7d58faa9a7473d27f5510d676af33282796f
-$ rad inspect --sigrefs rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add Bob" --description "" --threshold 2 --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm -q
+c7d68a801ed8c107521cb63b4089b4bd6601fad4
+$ rad inspect --sigrefs rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi [..] parent
z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk [..] parent
-z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z c9a828fc2fb01f893d6e6e9e17b9092dea2b3aba parent
+z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z 75f45dfa9e24758179f906e7bb7a453e00412f67 parent
```
``` ~bob
-$ rad watch --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --node z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z -r 'refs/rad/sigrefs' -t c9a828fc2fb01f893d6e6e9e17b9092dea2b3aba -i 500 --timeout 5000ms
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad watch --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --node z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z -r 'refs/rad/sigrefs' -t 75f45dfa9e24758179f906e7bb7a453e00412f67 -i 500 --timeout 5000ms
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-$ rad id --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad id --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created Parent │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 069e7d5 Add Bob alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi accepted now 0656c21 │
-│ ● 0656c21 Initial revision alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi accepted now none │
+│ ● c7d68a8 Add Bob alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi accepted now 8639908 │
+│ ● 8639908 Initial revision alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi accepted now none │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Hints:
@@ -26,20 +26,20 @@ Hints:
● accepted
● rejected:
✘ … by delegate votes ↥ … by parent ⇄ … by sibling
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --sigrefs
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --sigrefs
z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi [..] parent
z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk [..] root
z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z [..] parent
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --delegates
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm
-✓ Identity revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 created
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add Eve" --description "" --delegate did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z --no-confirm
+✓ Identity revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Eve │
-│ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 │
-│ Parent 069e7d58faa9a7473d27f5510d676af33282796f │
-│ Blob 74581605d1f75396c331487a10ca61c4815ed685 │
+│ Revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf │
+│ Parent c7d68a801ed8c107521cb63b4089b4bd6601fad4 │
+│ Blob 57dda7d9ab25ad958838e479c0c8e5ab7af56cd7 │
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State active │
│ Quorum no │
@@ -48,11 +48,22 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --des
│ ? did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,14 +1,15 @@
+@@ -1,24 +1,25 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -62,27 +73,26 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add Eve" --des
- "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
+ "did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
- ],
- "threshold": 2
+ ]
}
```
``` ~alice
-$ rad sync --fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+$ rad sync --fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --delegates
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-$ rad id accept 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --no-confirm
-✓ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 accepted
+$ rad id accept 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --no-confirm
+✓ Revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf accepted
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Eve │
-│ Revision 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 │
-│ Parent 069e7d58faa9a7473d27f5510d676af33282796f │
-│ Blob 74581605d1f75396c331487a10ca61c4815ed685 │
+│ Revision 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf │
+│ Parent c7d68a801ed8c107521cb63b4089b4bd6601fad4 │
+│ Blob 57dda7d9ab25ad958838e479c0c8e5ab7af56cd7 │
│ Author did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk │
│ State accepted │
│ Quorum yes │
@@ -90,15 +100,15 @@ $ rad id accept 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 --repo rad:z42hL2jL4XNk
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
│ ✓ did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk bob │
╰────────────────────────────────────────────────────────────────────────╯
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --delegates
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --delegates
did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi (alice)
did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z (eve)
```
``` ~alice
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Make private" --description "" --visibility private --no-confirm -q
-e6bf10593b78384eb2b281cbb18a605668a6d1f7
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Make private" --description "" --visibility private --no-confirm -q
+ec079dc70ee5279af315e281e37b6b989e6f73c4
```
We can list all revisions:
@@ -108,10 +118,10 @@ $ rad id list
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Status Created Parent │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● e6bf105 Make private alice (you) active now 3cd3c7f │
-│ ● 3cd3c7f Add Eve bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk accepted now 069e7d5 │
-│ ● 069e7d5 Add Bob alice (you) accepted now 0656c21 │
-│ ● 0656c21 Initial revision alice (you) accepted now none │
+│ ● ec079dc Make private alice (you) active now 46bb203 │
+│ ● 46bb203 Add Eve bob z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk accepted now c7d68a8 │
+│ ● c7d68a8 Add Bob alice (you) accepted now 8639908 │
+│ ● 8639908 Initial revision alice (you) accepted now none │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Hints:
@@ -124,25 +134,25 @@ Hints:
Despite being a delegate, Bob can't edit or redact Alice's revision:
``` ~bob (fail)
-$ rad id redact e6bf10593b78384eb2b281cbb18a605668a6d1f7
+$ rad id redact ec079dc70ee5279af315e281e37b6b989e6f73c4
[..]
```
``` ~bob (fail)
-$ rad id edit --title "Boo!" --description "Boo!" e6bf10593b78384eb2b281cbb18a605668a6d1f7
+$ rad id edit --title "Boo!" --description "Boo!" ec079dc70ee5279af315e281e37b6b989e6f73c4
[..]
```
Alice can edit:
``` ~alice
-$ rad id edit --title "Make private" --description "Privacy is cool." e6bf10593b78384eb2b281cbb18a605668a6d1f7
-✓ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7 edited
-$ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
+$ rad id edit --title "Make private" --description "Privacy is cool." ec079dc70ee5279af315e281e37b6b989e6f73c4
+✓ Revision ec079dc70ee5279af315e281e37b6b989e6f73c4 edited
+$ rad id show ec079dc70ee5279af315e281e37b6b989e6f73c4
╭────────────────────────────────────────────────────────────────────────╮
│ Title Make private │
-│ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7 │
-│ Parent 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 │
-│ Blob c533865b2846ca6c5b4436ec6872257293380c3b │
+│ Revision ec079dc70ee5279af315e281e37b6b989e6f73c4 │
+│ Parent 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf │
+│ Blob 530abcfb097cf9ea3f47139cc143b5678333ffb6 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │
│ Quorum no │
@@ -154,11 +164,22 @@ $ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
│ ? did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,15 +1,18 @@
+@@ -1,25 +1,28 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -167,9 +188,8 @@ $ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
"did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
- ],
-- "threshold": 2
-+ "threshold": 2,
+- ]
++ ],
+ "visibility": {
+ "type": "private"
+ }
@@ -179,23 +199,23 @@ $ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
And she can redact her revision:
``` ~alice
-$ rad id redact e6bf10593b78384eb2b281cbb18a605668a6d1f7
-✓ Revision e6bf10593b78384eb2b281cbb18a605668a6d1f7 redacted
+$ rad id redact ec079dc70ee5279af315e281e37b6b989e6f73c4
+✓ Revision ec079dc70ee5279af315e281e37b6b989e6f73c4 redacted
```
``` ~alice (fail)
-$ rad id show e6bf10593b78384eb2b281cbb18a605668a6d1f7
-✗ Error: revision `e6bf10593b78384eb2b281cbb18a605668a6d1f7` not found
+$ rad id show ec079dc70ee5279af315e281e37b6b989e6f73c4
+✗ Error: revision `ec079dc70ee5279af315e281e37b6b989e6f73c4` not found
```
Finally, Alice can also propose to remove Bob:
``` ~alice
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --description "" --rescind did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm
-✓ Identity revision 8ba242a80bc1181f41f9ea7a19286038c7948994 created
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Remove Bob" --description "" --rescind did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm
+✓ Identity revision 3940c10cb70dc6b52f9280d06c3cf0bc84d3b4a2 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Remove Bob │
-│ Revision 8ba242a80bc1181f41f9ea7a19286038c7948994 │
-│ Parent 3cd3c7f9900de0fcb19705856a7cc339a38fb0b3 │
-│ Blob 254d62de237117e7d7b9ceff85c47f5e3b610c1e │
+│ Revision 3940c10cb70dc6b52f9280d06c3cf0bc84d3b4a2 │
+│ Parent 46bb20352ca9d8c0a5b9fdccf17f66ff9f13aeaf │
+│ Blob 488e5cb72027dfc2b9e2b5a92ab6e1f8d8040609 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State active │
│ Quorum no │
@@ -205,11 +225,22 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --
│ ? did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z eve │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,15 +1,14 @@
+@@ -1,25 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -218,7 +249,6 @@ $ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Remove Bob" --
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
- "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk",
"did:key:z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z"
- ],
- "threshold": 2
+ ]
}
```
diff --git a/crates/radicle-cli/examples/rad-id-private.md b/crates/radicle-cli/examples/rad-id-private.md
index 711ee25e84..7dd833535c 100644
--- a/crates/radicle-cli/examples/rad-id-private.md
+++ b/crates/radicle-cli/examples/rad-id-private.md
@@ -9,9 +9,20 @@ $ rad id update --title "Allow Bob & Eve" --allow did:key:z6Mkt67GdsW7715MEfRuP4
...
$ rad inspect --identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "radicle heartwood protocol & stack",
"name": "heartwood"
}
@@ -19,7 +30,6 @@ $ rad inspect --identity
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
],
- "threshold": 1,
"visibility": {
"type": "private",
"allow": [
@@ -37,9 +47,20 @@ $ rad id update --title "Remove allow list" --disallow did:key:z6Mkt67GdsW7715ME
...
$ rad inspect --identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "radicle heartwood protocol & stack",
"name": "heartwood"
}
@@ -47,7 +68,6 @@ $ rad inspect --identity
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
],
- "threshold": 1,
"visibility": {
"type": "private"
}
diff --git a/crates/radicle-cli/examples/rad-id-threshold-soft-fork.md b/crates/radicle-cli/examples/rad-id-threshold-soft-fork.md
index 47a9682b10..5ccf761203 100644
--- a/crates/radicle-cli/examples/rad-id-threshold-soft-fork.md
+++ b/crates/radicle-cli/examples/rad-id-threshold-soft-fork.md
@@ -3,10 +3,10 @@ without having pushed the canonical default branch. For example, Bob can create
an issue in the repository:
``` ~bob
-$ rad issue open --title "Add Bob as a delegate" --description "We agreed to add me as a delegate, so I am creating an issue to track that work" --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad issue open --title "Add Bob as a delegate" --description "We agreed to add me as a delegate, so I am creating an issue to track that work" --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
╭──────────────────────────────────────────────────────────────╮
│ Title Add Bob as a delegate │
-│ Issue f12d512c51d30429f7916db038ae0360e2e938c2 │
+│ Issue aeb4689547ce516268521aa52e2c5649bcb91bfd │
│ Author bob (you) │
│ Status open │
│ │
@@ -24,7 +24,7 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
├── heads
│ └── master
└── rad
@@ -35,7 +35,7 @@ z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
└── refs
├── cobs
│ └── xyz.radicle.issue
- │ └── f12d512c51d30429f7916db038ae0360e2e938c2
+ │ └── aeb4689547ce516268521aa52e2c5649bcb91bfd
└── rad
├── root
└── sigrefs
@@ -46,5 +46,5 @@ as a delegate, since a threshold of 1 can still be reached:
``` ~alice
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk -q
-7be665f9fccba97abb21b2fa85a6fd3181c72858
+83ac41c238b1ece55e11ca0ad8621fe5013e30e5
```
diff --git a/crates/radicle-cli/examples/rad-id-threshold.md b/crates/radicle-cli/examples/rad-id-threshold.md
index 8ae1db0605..10b30c822c 100644
--- a/crates/radicle-cli/examples/rad-id-threshold.md
+++ b/crates/radicle-cli/examples/rad-id-threshold.md
@@ -7,8 +7,8 @@ can be updated.
``` ~alice (fail)
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --threshold 2
-✗ Error: failed to verify delegates for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✗ Error: the threshold of 2 delegates cannot be met..
+✗ Error: failed to verify delegates for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✗ Error: the required threshold of delegates cannot be met..
✗ Error: the delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk is missing
✗ Hint: run `rad follow did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk` to follow this missing peer
✗ Error: fatal: refusing to update identity document
@@ -18,12 +18,12 @@ Instead, Alice can simply keep the `threshold` as `1` and still add Bob as a del
``` ~alice
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-✓ Identity revision 7be665f9fccba97abb21b2fa85a6fd3181c72858 created
+✓ Identity revision 83ac41c238b1ece55e11ca0ad8621fe5013e30e5 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Bob │
-│ Revision 7be665f9fccba97abb21b2fa85a6fd3181c72858 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob 93d3009787e5d8a481dffc4dd248ea46af592466 │
+│ Revision 83ac41c238b1ece55e11ca0ad8621fe5013e30e5 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 0653b9dbe278688862856d37e1c6bb66ef35ebed │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -33,11 +33,22 @@ $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delega
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,14 @@
+@@ -1,23 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -46,8 +57,7 @@ $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delega
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 1
+ ]
}
```
@@ -66,7 +76,7 @@ $ git commit -v -m "Define power requirements"
``` ~alice (stderr) RAD_SOCKET=/dev/null
$ git push rad master
✓ Canonical reference refs/heads/master updated to target commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..3e674d1 master -> master
```
@@ -87,8 +97,8 @@ $ git commit -v -m "Add README file"
``` ~alice (stderr) RAD_SOCKET=/dev/null
$ git push rad HEAD:refs/patches
-✓ Patch b09b2aa0ee055671c811e9ad4ba73eed211ebaa3 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch a398ac1d69d987771b3390a8f2014d867d477643 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -96,8 +106,8 @@ Any other seeds can also still fetch changes from Alice without any
errors:
``` ~seed
-$ rad sync rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad sync rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G -f
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -110,9 +120,20 @@ The identity has the new delegate, while the `threshold` is still `1`
``` ~alice
$ rad inspect --identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -120,8 +141,7 @@ $ rad inspect --identity
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 1
+ ]
}
```
@@ -134,13 +154,13 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
- │ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
│ └── xyz.radicle.patch
- │ └── b09b2aa0ee055671c811e9ad4ba73eed211ebaa3
+ │ └── a398ac1d69d987771b3390a8f2014d867d477643
├── heads
│ ├── master
│ └── patches
- │ └── b09b2aa0ee055671c811e9ad4ba73eed211ebaa3
+ │ └── a398ac1d69d987771b3390a8f2014d867d477643
└── rad
├── id
├── root
@@ -152,7 +172,7 @@ Similarly, she still does not have Bob's `rad/sigrefs`:
``` ~alice
$ rad inspect --sigrefs
-z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi e5c200775dc6da38306f62c995df67a1ab1bf62d parent
+z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 6a365b1521af06ad9a3039c7d72604ba025fbc88 parent
```
And she can still list the project, without any worries:
@@ -162,7 +182,7 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public 3e674d1 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public 3e674d1 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -171,9 +191,9 @@ branch to `refs/heads/master` for this project, she can then use `rad
sync` and fetch his references:
``` ~bob
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -190,16 +210,16 @@ Run `cd ./heartwood` to go to the repository directory.
``` ~bob
$ cd heartwood
$ rad fork
-✓ Forked repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+✓ Forked repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
```
``` ~alice
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ rad inspect --sigrefs
-z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi e5c200775dc6da38306f62c995df67a1ab1bf62d parent
-z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk dace6fe948548168a2bb687718949d9b5d9076ee parent
+z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 6a365b1521af06ad9a3039c7d72604ba025fbc88 parent
+z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk 66f927b4cda7081e72b6dfb225ce686ef235749d parent
```
diff --git a/crates/radicle-cli/examples/rad-id-unauthorized-delegate.md b/crates/radicle-cli/examples/rad-id-unauthorized-delegate.md
index b0dd76f440..9a16e053ac 100644
--- a/crates/radicle-cli/examples/rad-id-unauthorized-delegate.md
+++ b/crates/radicle-cli/examples/rad-id-unauthorized-delegate.md
@@ -1,7 +1,7 @@
-Alice has created a new repository `rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji` with only herself as the sole delegate. After Bob has cloned it, let's ensure he can't add himself as a delegate too:
+Alice has created a new repository `rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G` with only herself as the sole delegate. After Bob has cloned it, let's ensure he can't add himself as a delegate too:
``` ~bob (fail)
-$ rad id update --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --title "Add myself!" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm
+$ rad id update --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --title "Add myself!" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --no-confirm
✗ Error: did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk is not a delegate, and only delegates are allowed to create a revision
✗ Hint: bob (you) is attempting to modify the identity document but is not a delegate!
```
diff --git a/crates/radicle-cli/examples/rad-id-unknown-field.md b/crates/radicle-cli/examples/rad-id-unknown-field.md
index 31dea03af8..c688692a69 100644
--- a/crates/radicle-cli/examples/rad-id-unknown-field.md
+++ b/crates/radicle-cli/examples/rad-id-unknown-field.md
@@ -3,12 +3,12 @@ added. Here we will add an emoji alias for the heartwood project:
```
$ rad id update --title "Add emoji alias" --description "Adding alias field" --payload xyz.radicle.project alias '"❤️🪵"'
-✓ Identity revision 05100d3f0a73b9373681677158615a53ba51940e created
+✓ Identity revision 095516e23373bd6b868f46b017893008edba4439 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add emoji alias │
-│ Revision 05100d3f0a73b9373681677158615a53ba51940e │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob a0f421c928dcfc6eca129fc2ea1f50877de7dc20 │
+│ Revision 095516e23373bd6b868f46b017893008edba4439 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 2c87f6c8d62a9a0c0f95b333900272d477c291a7 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -18,20 +18,30 @@ $ rad id update --title "Add emoji alias" --description "Adding alias field" --p
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,14 @@
+@@ -1,23 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
+ "alias": "❤️🪵",
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
@@ -43,6 +53,6 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-id-update-delete-field.md b/crates/radicle-cli/examples/rad-id-update-delete-field.md
index 968bb33b56..ea21a6c7c6 100644
--- a/crates/radicle-cli/examples/rad-id-update-delete-field.md
+++ b/crates/radicle-cli/examples/rad-id-update-delete-field.md
@@ -2,12 +2,12 @@ Let's add a payload field and then delete it.
```
$ rad id update --title "Add field" --description "Add a new 'web' field" --payload xyz.radicle.project web '"https://acme.example"'
-✓ Identity revision a8a9fee6c4f83578ab132d375f1da0c81282bef3 created
+✓ Identity revision 0e4955004e8340b3bb874da7aa5b5a0fcad51b73 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add field │
-│ Revision a8a9fee6c4f83578ab132d375f1da0c81282bef3 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob fbe268d13e60f1f3a1972e0ccd592f3cdecf08b5 │
+│ Revision 0e4955004e8340b3bb874da7aa5b5a0fcad51b73 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 8e175fd5bbc3ffea7e654964e7fb321b2d897aea │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -17,11 +17,22 @@ $ rad id update --title "Add field" --description "Add a new 'web' field" --payl
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,14 @@
+@@ -1,23 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
- "name": "heartwood"
+ "name": "heartwood",
@@ -30,8 +41,7 @@ $ rad id update --title "Add field" --description "Add a new 'web' field" --payl
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
@@ -39,12 +49,12 @@ Now let's delete it by setting it to `null`.
```
$ rad id update --title "Delete field" --description "Delete 'web'" --payload xyz.radicle.project web null
-✓ Identity revision d373c35876833105f8aafed8b610660b5737cd67 created
+✓ Identity revision ab26ce0dfca6e3df7adf8c918825711336e21ce5 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Delete field │
-│ Revision d373c35876833105f8aafed8b610660b5737cd67 │
-│ Parent a8a9fee6c4f83578ab132d375f1da0c81282bef3 │
-│ Blob d96f425412c9f8ad5d9a9a05c9831d0728e2338d │
+│ Revision ab26ce0dfca6e3df7adf8c918825711336e21ce5 │
+│ Parent 0e4955004e8340b3bb874da7aa5b5a0fcad51b73 │
+│ Blob f10bd9e36848dc4eb70cc078d1d0bbaac7c1ba61 │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -54,11 +64,22 @@ $ rad id update --title "Delete field" --description "Delete 'web'" --payload xy
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,14 +1,13 @@
+@@ -1,24 +1,23 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
- "name": "heartwood",
- "web": "https://acme.example"
@@ -67,14 +88,13 @@ $ rad id update --title "Delete field" --description "Delete 'web'" --payload xy
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
Note that we cannot delete mandatory fields:
``` (fails)
-$ rad id update --title "Delete default branch" --payload xyz.radicle.project defaultBranch null
-✗ Error: failed to verify `xyz.radicle.project`, missing field `defaultBranch`
+$ rad id update --title "Delete name" --payload xyz.radicle.project name null
+✗ Error: failed to verify `xyz.radicle.project`, missing field `name`
```
diff --git a/crates/radicle-cli/examples/rad-id.md b/crates/radicle-cli/examples/rad-id.md
index 6fcd3d5f00..2f8ae5b79b 100644
--- a/crates/radicle-cli/examples/rad-id.md
+++ b/crates/radicle-cli/examples/rad-id.md
@@ -15,12 +15,12 @@ threshold to `2`.
```
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --threshold 2
-✓ Identity revision 0ca42d376bd566631083c8913cf86bec722da392 created
+✓ Identity revision 491c96a516cd9ed236f83e2e2d52d8799f31f4b4 created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Bob │
-│ Revision 0ca42d376bd566631083c8913cf86bec722da392 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob 053541ba7b90534b35dd8718e0ceaa408979b02b │
+│ Revision 491c96a516cd9ed236f83e2e2d52d8799f31f4b4 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 4b49080fa898fea405a320fe68c10ee9e3fa559d │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -30,11 +30,23 @@ $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delega
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,14 @@
+@@ -1,23 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+- "threshold": 1
++ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -43,9 +55,7 @@ $ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delega
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
-- "threshold": 1
-+ "threshold": 2
+ ]
}
```
@@ -77,9 +87,20 @@ can verify that by listing the current identity document:
```
$ rad inspect --identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -87,16 +108,15 @@ $ rad inspect --identity
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
"did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
- "threshold": 2
+ ]
}
```
We can also look at the document's COB directly:
```
-$ rad cob log --object 0656c217f917c3e06234771e9ecae53aba5e173e --type xyz.radicle.id --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-commit 0ca42d376bd566631083c8913cf86bec722da392
-parent 0656c217f917c3e06234771e9ecae53aba5e173e
+$ rad cob log --object 86399084097fb674569f5bc5847da609ab91aa9f --type xyz.radicle.id --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+commit 491c96a516cd9ed236f83e2e2d52d8799f31f4b4
+parent 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
@@ -104,21 +124,21 @@ date Thu, 15 Dec 2022 17:28:04 +0000
"type": "revision",
"title": "Add Bob",
"description": "Add Bob as a delegate",
- "blob": "053541ba7b90534b35dd8718e0ceaa408979b02b",
- "parent": "0656c217f917c3e06234771e9ecae53aba5e173e",
- "signature": "z3AyzixN2eWLtRfQWowtBXwWyRH3iJ8oJ25W6KFYFw5ANLntbzfavge15muNU6AVAUkxSxQvgg9yh2gupbUecavQY"
+ "blob": "4b49080fa898fea405a320fe68c10ee9e3fa559d",
+ "parent": "86399084097fb674569f5bc5847da609ab91aa9f",
+ "signature": "z3a5oLvRLXLi6aoXUqzWpbT5n4MHstpvHCpmb2p5KVVdKNJzyoKgEFNtk7554SwvtgMhgnpwAqK1JnzT9DFTtwDE8"
}
-commit 0656c217f917c3e06234771e9ecae53aba5e173e
+commit 86399084097fb674569f5bc5847da609ab91aa9f
author z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
date Thu, 15 Dec 2022 17:28:04 +0000
{
"type": "revision",
"title": "Initial revision",
- "blob": "d96f425412c9f8ad5d9a9a05c9831d0728e2338d",
+ "blob": "f10bd9e36848dc4eb70cc078d1d0bbaac7c1ba61",
"parent": null,
- "signature": "z5nGqUvrmfiSyLjNCHWTWYvVMcPUZcvo9TxPKzEKXYBdSgUzbrqf1cYsmpGgbQvYunnsrLSsubEmxZaRdKM4quqQR"
+ "signature": "zWUiHpVnmzm6Hd5aUphUdHABCtMUHQCfGYLthhXgmEDNCqTrrPLiBRMEopxYF7WUfoR2ZUEpqjPMjENPBNBjAPe7"
}
```
@@ -126,12 +146,12 @@ date Thu, 15 Dec 2022 17:28:04 +0000
We can use `rad id show` to show the changes of an accepted update:
```
-$ rad id show 0ca42d376bd566631083c8913cf86bec722da392
+$ rad id show 491c96a516cd9ed236f83e2e2d52d8799f31f4b4
╭────────────────────────────────────────────────────────────────────────╮
│ Title Add Bob │
-│ Revision 0ca42d376bd566631083c8913cf86bec722da392 │
-│ Parent 0656c217f917c3e06234771e9ecae53aba5e173e │
-│ Blob 053541ba7b90534b35dd8718e0ceaa408979b02b │
+│ Revision 491c96a516cd9ed236f83e2e2d52d8799f31f4b4 │
+│ Parent 86399084097fb674569f5bc5847da609ab91aa9f │
+│ Blob 4b49080fa898fea405a320fe68c10ee9e3fa559d │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -141,11 +161,23 @@ $ rad id show 0ca42d376bd566631083c8913cf86bec722da392
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,14 @@
+@@ -1,23 +1,24 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+- "threshold": 1
++ "threshold": 2
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -154,9 +186,7 @@ $ rad id show 0ca42d376bd566631083c8913cf86bec722da392
- "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
+ "did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi",
+ "did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk"
- ],
-- "threshold": 1
-+ "threshold": 2
+ ]
}
```
@@ -164,15 +194,15 @@ Note that once a revision is accepted, it can't be edited, redacted or otherwise
acted upon:
``` (fail)
-$ rad id redact 0ca42d376bd566631083c8913cf86bec722da392
+$ rad id redact 491c96a516cd9ed236f83e2e2d52d8799f31f4b4
✗ Error: [..]
```
``` (fail)
-$ rad id reject 0ca42d376bd566631083c8913cf86bec722da392
+$ rad id reject 491c96a516cd9ed236f83e2e2d52d8799f31f4b4
✗ Error: [..]
```
``` (fail)
-$ rad id accept 0ca42d376bd566631083c8913cf86bec722da392
+$ rad id accept 491c96a516cd9ed236f83e2e2d52d8799f31f4b4
✗ Error: [..]
```
diff --git a/crates/radicle-cli/examples/rad-inbox.md b/crates/radicle-cli/examples/rad-inbox.md
index 1e3e447bd5..537199a52c 100644
--- a/crates/radicle-cli/examples/rad-inbox.md
+++ b/crates/radicle-cli/examples/rad-inbox.md
@@ -125,16 +125,26 @@ $ rad inbox --all
╰──────────────────────────────────────────────────────────────────────╯
$ rad inbox show 1
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "https://radicle.dev",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
diff --git a/crates/radicle-cli/examples/rad-init-existing-bare.md b/crates/radicle-cli/examples/rad-init-existing-bare.md
index f2c88a7e13..3b093f91fd 100644
--- a/crates/radicle-cli/examples/rad-init-existing-bare.md
+++ b/crates/radicle-cli/examples/rad-init-existing-bare.md
@@ -14,19 +14,19 @@ $ rad .
Let's pick an existing repository:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
And initialize this working copy as that existing repository:
```
-$ rad init --setup-signing --existing rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad init --setup-signing --existing rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
Configuring Radicle signing key SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA…
✓ Signing configured in [..]/heartwood/config
! Not writing .gitsigners file.
-✓ Initialized existing repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji in [..]/heartwood/..
+✓ Initialized existing repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G in [..]/heartwood/..
```
The warning about not writing `.gitsigners` is expected, as this requires a
@@ -35,11 +35,11 @@ working directory, which a bare repository does not have.
We can confirm that the working copy is initialized:
```
$ rad .
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
$ git remote show rad
* remote rad
- Fetch URL: rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
- Push URL: rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ Fetch URL: rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+ Push URL: rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
HEAD branch: master
Remote branch:
master new (next fetch will store in remotes/rad)
diff --git a/crates/radicle-cli/examples/rad-init-existing.md b/crates/radicle-cli/examples/rad-init-existing.md
index 8ec0eb3fef..6f5f5811f5 100644
--- a/crates/radicle-cli/examples/rad-init-existing.md
+++ b/crates/radicle-cli/examples/rad-init-existing.md
@@ -14,29 +14,29 @@ $ rad .
Let's pick an existing repository:
```
-$ rad inspect rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad inspect rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
And initialize this working copy as that existing repository:
```
-$ rad init --setup-signing --existing rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad init --setup-signing --existing rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
Configuring Radicle signing key SHA256:UIedaL6Cxm6OUErh9GQUzzglSk7VpQlVTI1TAFB/HWA…
✓ Signing configured in [..]/heartwood/.git/config
✓ Created .gitsigners file
-✓ Initialized existing repository rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji in [..]/heartwood/..
+✓ Initialized existing repository rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G in [..]/heartwood/..
```
We can confirm that the working copy is initialized:
```
$ rad .
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
$ git remote show rad
* remote rad
- Fetch URL: rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
- Push URL: rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ Fetch URL: rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+ Push URL: rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
HEAD branch: master
Remote branch:
master new (next fetch will store in remotes/rad)
diff --git a/crates/radicle-cli/examples/rad-init-no-seed.md b/crates/radicle-cli/examples/rad-init-no-seed.md
index d42deb6aae..d865bd81b9 100644
--- a/crates/radicle-cli/examples/rad-init-no-seed.md
+++ b/crates/radicle-cli/examples/rad-init-no-seed.md
@@ -6,7 +6,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
+Your Repository ID (RID) is rad:z41A7PnmXror3L2oP1vq81vhCQPBc
You can show it any time by running `rad .` from this directory.
Your repository will be announced to the network when you start your node.
@@ -19,11 +19,11 @@ $ rad node inventory
If we then seed it, it becomes advertised in our inventory:
```
-$ rad seed rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
-✓ Inventory updated with rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
-✓ Seeding policy updated for rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK with scope 'followed'
+$ rad seed rad:z41A7PnmXror3L2oP1vq81vhCQPBc
+✓ Inventory updated with rad:z41A7PnmXror3L2oP1vq81vhCQPBc
+✓ Seeding policy updated for rad:z41A7PnmXror3L2oP1vq81vhCQPBc with scope 'followed'
```
```
$ rad node inventory
-rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
+rad:z41A7PnmXror3L2oP1vq81vhCQPBc
```
diff --git a/crates/radicle-cli/examples/rad-init-private-clone-seed.md b/crates/radicle-cli/examples/rad-init-private-clone-seed.md
index 17fc6124e5..21e8190d48 100644
--- a/crates/radicle-cli/examples/rad-init-private-clone-seed.md
+++ b/crates/radicle-cli/examples/rad-init-private-clone-seed.md
@@ -1,4 +1,4 @@
-Given a private repo `rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu` belonging to Alice,
+Given a private repo `rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2` belonging to Alice,
Alice allows Bob to fetch it, and Bob, without the updated identity document
is able to fetch it by specifying Alice as a seed.
@@ -7,9 +7,20 @@ $ rad id update --title "Allow Bob" --description "" --allow did:key:z6Mkt67GdsW
...
$ rad inspect --identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "radicle heartwood protocol & stack",
"name": "heartwood"
}
@@ -17,7 +28,6 @@ $ rad inspect --identity
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
],
- "threshold": 1,
"visibility": {
"type": "private",
"allow": [
@@ -29,14 +39,14 @@ $ rad inspect --identity
``` ~bob
$ rad ls --all --private
-$ rad clone rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
-✓ Seeding policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'followed'
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
+$ rad clone rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
+✓ Seeding policy updated for rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 with scope 'followed'
+Fetching rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 from the network, found 1 potential seed(s).
✓ Target met: 1 preferred seed(s).
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-✓ Repository successfully cloned under [...]/.radicle/heartwood/
+✓ Repository successfully cloned under [..]/.radicle/heartwood/
╭────────────────────────────────────╮
│ heartwood │
│ radicle heartwood protocol & stack │
@@ -48,8 +58,8 @@ Run `cd ./heartwood` to go to the repository directory.
We can also use `rad seed` to seed and fetch without creating a checkout.
``` ~bob
-$ rad seed rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
-✓ Seeding policy exists for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'followed'
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
+$ rad seed rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 --from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
+✓ Seeding policy exists for rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 with scope 'followed'
+Fetching rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
```
diff --git a/crates/radicle-cli/examples/rad-init-private-clone.md b/crates/radicle-cli/examples/rad-init-private-clone.md
index 5f0f2519e3..485d38857c 100644
--- a/crates/radicle-cli/examples/rad-init-private-clone.md
+++ b/crates/radicle-cli/examples/rad-init-private-clone.md
@@ -1,17 +1,17 @@
-Given a private repo `rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu` belonging to Alice,
+Given a private repo `rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2` belonging to Alice,
Bob tries to fetch it, and even though he's connected to Alice, it fails.
``` ~bob
$ rad ls
```
``` ~bob (fail)
-$ rad clone rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
-✓ Seeding policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'followed'
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
+$ rad clone rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --timeout 1s
+✓ Seeding policy updated for rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 with scope 'followed'
+Fetching rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 from the network, found 1 potential seed(s).
✗ Target not met: could not fetch from [z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi], and required 1 more seed(s)
! Warning: Failed to fetch from 1 seed(s).
! Warning: z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi: an I/O error occurred during the fetch handshake (connection reset)
-✗ Error: no seeds found for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
+✗ Error: no seeds found for rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2
```
She allows Bob to view the repository. And when she syncs, one seed (Bob) gets
@@ -28,15 +28,15 @@ Bob can now fetch the private repo without specifying a seed, because he knows
that Alice has the repo after she announced her refs:
``` ~bob
-$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
+$ rad sync rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 --fetch
+Fetching rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ rad ls --private --all
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu private f2de534 radicle heartwood protocol & stack │
+│ heartwood rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 private f2de534 radicle heartwood protocol & stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-init-private-no-seed.md b/crates/radicle-cli/examples/rad-init-private-no-seed.md
index 261f19a32d..fbe76c39d2 100644
--- a/crates/radicle-cli/examples/rad-init-private-no-seed.md
+++ b/crates/radicle-cli/examples/rad-init-private-no-seed.md
@@ -9,7 +9,7 @@ Initializing private Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
+Your Repository ID (RID) is rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2
You can show it any time by running `rad .` from this directory.
You have created a private repository.
@@ -27,8 +27,8 @@ No seeding policies to show.
We can decide to seed it later, so that others can fetch it from us, given
that they are part of the allow list:
```
-$ rad seed rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
-✓ Seeding policy updated for rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu with scope 'followed'
+$ rad seed rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2
+✓ Seeding policy updated for rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 with scope 'followed'
```
But it still won't show up in our inventory, since it's private:
diff --git a/crates/radicle-cli/examples/rad-init-private-seed.md b/crates/radicle-cli/examples/rad-init-private-seed.md
index 987061a45a..1706ac4a0c 100644
--- a/crates/radicle-cli/examples/rad-init-private-seed.md
+++ b/crates/radicle-cli/examples/rad-init-private-seed.md
@@ -9,41 +9,41 @@ $ rad id update --title "Allow Bob" --description "" --allow did:key:z6Mkt67GdsW
First, Bob seeds the repo.
``` ~bob
-$ rad seed rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --no-fetch
+$ rad seed rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch --no-fetch
[..]
```
If Bob just tries to fetch it without specifying seeds, he gets an error:
``` ~bob (fails)
-$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch
+$ rad sync rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch --fetch
✗ Error: no candidate seeds were found to fetch from
```
He has to specify a seed that isn't in his routing table:
``` ~bob
-$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
-✓ Target met: 1 preferred seed(s).
-🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+$ rad sync rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch --fetch --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+Fetching rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch from the network, found 1 potential seed(s).
+✗ Target not met: could not fetch from [z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi], and required 1 more seed(s)
+✗ Error: Fetched from 0 preferred seed(s), could not reach 1 seed(s)
+✗ Error: Could not replicate from 1 preferred seed(s)
+✗ Error: z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi: an I/O error occurred during the fetch handshake (connection reset)
```
``` ~bob
$ rad ls --private --all
-╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
-│ Name RID Visibility Head Description │
-├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu private f2de534 radicle heartwood protocol & stack │
-╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
Note that if multiple seeds are specified, the command succeeds as long as one
seed succeeds.
``` ~bob
-$ rad sync rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu --fetch --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --seed z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx
-Fetching rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu from the network, found 1 potential seed(s).
-✓ Target met: 1 seed(s)
-🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+$ rad sync rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch --fetch --seed z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --seed z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx
+Fetching rad:z2X6q6YBaYvKvURP1SvbzTgqa8tch from the network, found 2 potential seed(s).
+✗ Target not met: could not fetch from [z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi, z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx], and required 2 more seed(s)
+✗ Error: Fetched from 0 preferred seed(s), could not reach 2 seed(s)
+✗ Error: Could not replicate from 2 preferred seed(s)
+✗ Error: z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi: an I/O error occurred during the fetch handshake (connection reset)
+✗ Error: z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx: Could not connect. No addresses known.
```
diff --git a/crates/radicle-cli/examples/rad-init-private.md b/crates/radicle-cli/examples/rad-init-private.md
index 0ac776c8a3..03599a1d32 100644
--- a/crates/radicle-cli/examples/rad-init-private.md
+++ b/crates/radicle-cli/examples/rad-init-private.md
@@ -7,7 +7,7 @@ Initializing private Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
+Your Repository ID (RID) is rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2
You can show it any time by running `rad .` from this directory.
You have created a private repository.
@@ -25,6 +25,6 @@ $ rad seed
╭────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├────────────────────────────────────────────────────────────────┤
-│ rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu heartwood allow all │
+│ rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2 heartwood allow all │
╰────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-init-sync-not-connected.md b/crates/radicle-cli/examples/rad-init-sync-not-connected.md
index 15343722cb..35d9e0ccc4 100644
--- a/crates/radicle-cli/examples/rad-init-sync-not-connected.md
+++ b/crates/radicle-cli/examples/rad-init-sync-not-connected.md
@@ -7,7 +7,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+Your Repository ID (RID) is rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
You can show it any time by running `rad .` from this directory.
✗ Announcing.. <canceled>
diff --git a/crates/radicle-cli/examples/rad-init-sync-preferred.md b/crates/radicle-cli/examples/rad-init-sync-preferred.md
index 2e958d7cf7..d52bbfceee 100644
--- a/crates/radicle-cli/examples/rad-init-sync-preferred.md
+++ b/crates/radicle-cli/examples/rad-init-sync-preferred.md
@@ -7,7 +7,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW
+Your Repository ID (RID) is rad:z45hwUDmwBidvbiZdL1oLYkzir9gD
You can show it any time by running `rad .` from this directory.
✓ Repository successfully synced to z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -16,7 +16,7 @@ You can show it any time by running `rad .` from this directory.
Your repository has been synced to the network and is now discoverable by peers.
View it in your browser at:
- https://radicle.network/nodes/[...]/rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW
+ https://radicle.network/nodes/127.0.0.1/rad:z45hwUDmwBidvbiZdL1oLYkzir9gD
To push changes, run `git push`.
```
diff --git a/crates/radicle-cli/examples/rad-init-sync-timeout.md b/crates/radicle-cli/examples/rad-init-sync-timeout.md
index 48ed15870c..570bfe3eed 100644
--- a/crates/radicle-cli/examples/rad-init-sync-timeout.md
+++ b/crates/radicle-cli/examples/rad-init-sync-timeout.md
@@ -8,7 +8,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW
+Your Repository ID (RID) is rad:z45hwUDmwBidvbiZdL1oLYkzir9gD
You can show it any time by running `rad .` from this directory.
✓ Repository successfully announced to the network.
diff --git a/crates/radicle-cli/examples/rad-init-sync.md b/crates/radicle-cli/examples/rad-init-sync.md
index 467f8c1310..982a2b2473 100644
--- a/crates/radicle-cli/examples/rad-init-sync.md
+++ b/crates/radicle-cli/examples/rad-init-sync.md
@@ -9,7 +9,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+Your Repository ID (RID) is rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
You can show it any time by running `rad .` from this directory.
✓ Repository successfully announced to the network.
diff --git a/crates/radicle-cli/examples/rad-init-v1.md b/crates/radicle-cli/examples/rad-init-v1.md
new file mode 100644
index 0000000000..78787b698c
--- /dev/null
+++ b/crates/radicle-cli/examples/rad-init-v1.md
@@ -0,0 +1,17 @@
+A repository can be initialized at an older identity document version, so that
+it stays readable to releases that predate the current version.
+
+```
+$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --identity-version 1 --no-confirm --public
+
+Initializing public Radicle 👾 repository in [..]
+
+✓ Repository heartwood created.
+
+Your Repository ID (RID) is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+You can show it any time by running `rad .` from this directory.
+
+Your repository will be announced to the network when you start your node.
+You can start your node with `rad node start`.
+To push changes, run `git push`.
+```
diff --git a/crates/radicle-cli/examples/rad-init-with-existing-remote.md b/crates/radicle-cli/examples/rad-init-with-existing-remote.md
index e056c94517..db36c25274 100644
--- a/crates/radicle-cli/examples/rad-init-with-existing-remote.md
+++ b/crates/radicle-cli/examples/rad-init-with-existing-remote.md
@@ -26,7 +26,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:z2D6wQnKapY7dn5meBnbH2rUKNZbT
+Your Repository ID (RID) is rad:z28iHDqGx6PGukSRwtVZkpbtQoRkF
You can show it any time by running `rad .` from this directory.
Your repository will be announced to the network when you start your node.
diff --git a/crates/radicle-cli/examples/rad-init.md b/crates/radicle-cli/examples/rad-init.md
index 8f0031758f..fe37b6c46f 100644
--- a/crates/radicle-cli/examples/rad-init.md
+++ b/crates/radicle-cli/examples/rad-init.md
@@ -10,11 +10,10 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
{
"name": "heartwood",
- "description": "Radicle Heartwood Protocol & Stack",
- "defaultBranch": "master"
+ "description": "Radicle Heartwood Protocol & Stack"
}
-Your Repository ID (RID) is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+Your Repository ID (RID) is rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
You can show it any time by running `rad .` from this directory.
Your repository will be announced to the network when you start your node.
@@ -26,7 +25,7 @@ If we try to initialize it again, we get an error:
``` (fail)
$ rad init
-✗ Error: repository is already initialized with remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+✗ Error: repository is already initialized with remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
Repositories can be listed with the `ls` command:
@@ -36,7 +35,7 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -44,5 +43,5 @@ Public repositories are added to our inventory:
```
$ rad node inventory
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
diff --git a/crates/radicle-cli/examples/rad-inspect-noauth.md b/crates/radicle-cli/examples/rad-inspect-noauth.md
index 0871afd304..0c5cc277f8 100644
--- a/crates/radicle-cli/examples/rad-inspect-noauth.md
+++ b/crates/radicle-cli/examples/rad-inspect-noauth.md
@@ -8,5 +8,5 @@ $ rad self
```
$ rad inspect
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
diff --git a/crates/radicle-cli/examples/rad-inspect.md b/crates/radicle-cli/examples/rad-inspect.md
index 6ad1edb37a..734421da7c 100644
--- a/crates/radicle-cli/examples/rad-inspect.md
+++ b/crates/radicle-cli/examples/rad-inspect.md
@@ -3,14 +3,14 @@ command from inside a working copy:
```
$ rad inspect
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
As a shorthand, you can also simply use `rad .`:
```
$ rad .
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
It's also possible to display all of the repository's git references:
@@ -21,7 +21,7 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ └── xyz.radicle.id
- │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
├── heads
│ └── master
└── rad
@@ -34,7 +34,7 @@ And sigrefs:
```
$ rad inspect --sigrefs
-z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 99c549702e2bcfe02b0e68d4a2224fb7a1524529 root
+z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 68a0f0d5d4d400f8788fdd8f6c515d0da6fa09be root
```
Or display the repository identity's payload and delegates:
@@ -42,8 +42,18 @@ Or display the repository identity's payload and delegates:
```
$ rad inspect --payload
{
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
@@ -57,24 +67,34 @@ history:
```
$ rad inspect --history
-commit 0656c217f917c3e06234771e9ecae53aba5e173e
-blob d96f425412c9f8ad5d9a9a05c9831d0728e2338d
+commit 86399084097fb674569f5bc5847da609ab91aa9f
+blob f10bd9e36848dc4eb70cc078d1d0bbaac7c1ba61
date Thu, 15 Dec 2022 17:28:04 +0000
Initialize identity
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "Radicle Heartwood Protocol & Stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
- "threshold": 1
+ ]
}
```
diff --git a/crates/radicle-cli/examples/rad-issue-list.md b/crates/radicle-cli/examples/rad-issue-list.md
index a3cfdf8cbc..d12a20ba75 100644
--- a/crates/radicle-cli/examples/rad-issue-list.md
+++ b/crates/radicle-cli/examples/rad-issue-list.md
@@ -5,14 +5,14 @@ $ rad issue list
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue now │
+│ ● cb9d978 flux capacitor underpowered alice (you) good-first-issue now │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
We can now assign ourselves to the open issue.
```
-$ rad issue assign d87dcfe --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
+$ rad issue assign cb9d978 --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
```
It will now also show up in the list of issues assigned to us.
@@ -22,15 +22,15 @@ $ rad issue list --assigned me
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │
+│ ● cb9d978 flux capacitor underpowered alice (you) good-first-issue alice now │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
If we now fix this issue, we can close it.
```
-$ rad issue state --solved d87dcfe --no-announce
-✓ Issue d87dcfe is now solved
+$ rad issue state --solved cb9d978 --no-announce
+✓ Issue cb9d978 is now solved
```
It will not show up in the list of open issues anymore.
@@ -46,7 +46,7 @@ $ rad issue list --solved
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │
+│ ● cb9d978 flux capacitor underpowered alice (you) good-first-issue alice now │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -57,6 +57,6 @@ $ rad issue --solved
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │
+│ ● cb9d978 flux capacitor underpowered alice (you) good-first-issue alice now │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-issue.md b/crates/radicle-cli/examples/rad-issue.md
index eb97ef4266..867554c01d 100644
--- a/crates/radicle-cli/examples/rad-issue.md
+++ b/crates/radicle-cli/examples/rad-issue.md
@@ -7,7 +7,7 @@ Let's say the new car you are designing with your peers has a problem with its f
$ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue d87dcfe8c2b3200e78b128d9b959cfdf7063fefe │
+│ Issue cb9d9788d1854a6d4bc7235756df33b9d372a605 │
│ Author alice (you) │
│ Status open │
│ │
@@ -22,17 +22,17 @@ $ rad issue list
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├──────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) now │
+│ ● cb9d978 flux capacitor underpowered alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────╯
```
Show the issue information issue.
```
-$ rad issue show d87dcfe
+$ rad issue show cb9d978
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue d87dcfe8c2b3200e78b128d9b959cfdf7063fefe │
+│ Issue cb9d9788d1854a6d4bc7235756df33b9d372a605 │
│ Author alice (you) │
│ Status open │
│ │
@@ -51,8 +51,8 @@ Let's assign ourselves to this one, this is to ensure work is not
duplicated. While we're at it, let's add a label.
```
-$ rad issue assign d87dcfe --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
-$ rad issue label d87dcfe --add good-first-issue --no-announce
+$ rad issue assign cb9d978 --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
+$ rad issue label cb9d978 --add good-first-issue --no-announce
```
It will now show in the list of issues assigned to us, along with the new label.
@@ -62,14 +62,14 @@ $ rad issue list --assigned
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● d87dcfe flux capacitor underpowered alice (you) good-first-issue alice now │
+│ ● cb9d978 flux capacitor underpowered alice (you) good-first-issue alice now │
╰────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
Note: this can always be undone with the `unassign` subcommand.
```
-$ rad issue assign d87dcfe --delete did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
+$ rad issue assign cb9d978 --delete did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
```
Great, now we have communicated to the world about our car's defect.
@@ -78,30 +78,30 @@ But wait! We've found an important detail about the car's power requirements.
It will help whoever works on a fix.
```
-$ rad issue comment d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --message 'The flux capacitor needs 1.21 Gigawatts' -q --no-announce
-2193e871916d18ddd0416b5198cb08c5dc7416b7
-$ rad issue comment d87dcfe8c2b3200e78b128d9b959cfdf7063fefe --reply-to 2193e871916d18ddd0416b5198cb08c5dc7416b7 --message 'More power!' -q --no-announce
-880fdcd94b36e412fc906b510f41008700d65424
+$ rad issue comment cb9d9788d1854a6d4bc7235756df33b9d372a605 --message 'The flux capacitor needs 1.21 Gigawatts' -q --no-announce
+7bec223a4952f6b402385c804df44e1231871449
+$ rad issue comment cb9d9788d1854a6d4bc7235756df33b9d372a605 --reply-to 7bec223a4952f6b402385c804df44e1231871449 --message 'More power!' -q --no-announce
+2ad1eb1cbf0026fd737c691d55d39f41e2065cd1
```
We can see our comments by showing the issue:
```
-$ rad issue show d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
+$ rad issue show cb9d9788d1854a6d4bc7235756df33b9d372a605
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue d87dcfe8c2b3200e78b128d9b959cfdf7063fefe │
+│ Issue cb9d9788d1854a6d4bc7235756df33b9d372a605 │
│ Author alice (you) │
│ Labels good-first-issue │
│ Status open │
│ │
│ Flux capacitor power requirements exceed current supply │
├─────────────────────────────────────────────────────────┤
-│ alice (you) now 2193e87 │
+│ alice (you) now 7bec223 │
│ │
│ The flux capacitor needs 1.21 Gigawatts │
├─────────────────────────────────────────────────────────┤
-│ alice (you) now 880fdcd │
+│ alice (you) now 2ad1eb1 │
│ │
│ More power! │
╰─────────────────────────────────────────────────────────╯
@@ -110,9 +110,9 @@ $ rad issue show d87dcfe8c2b3200e78b128d9b959cfdf7063fefe
We can also edit a comment:
```
-$ rad issue comment d87dcfe --edit 880fdcd -m "Even more power!"
+$ rad issue comment cb9d978 --edit 7bec223 -m "Even more power!"
╭─────────────────────────╮
-│ alice (you) now 880fdcd │
+│ alice (you) now 7bec223 │
│ Even more power! │
╰─────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-merge-after-update.md b/crates/radicle-cli/examples/rad-merge-after-update.md
index 945dd57fc6..36308726ae 100644
--- a/crates/radicle-cli/examples/rad-merge-after-update.md
+++ b/crates/radicle-cli/examples/rad-merge-after-update.md
@@ -4,8 +4,8 @@ Let's start by creating a patch.
$ git checkout -b feature/1 -q
$ git commit --allow-empty -q -m "First change"
$ git push rad HEAD:refs/patches
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -17,7 +17,7 @@ $ git checkout master -q
$ git merge feature/1 -q
$ git push rad master
✓ Canonical reference refs/heads/master updated to target commit 954bcdb5008447ce294a61a21d7eb87afbe7f4a6
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..954bcdb master -> master
```
@@ -27,8 +27,8 @@ update it, we expect it to be updated and merged:
``` (stderr) RAD_SOCKET=/dev/null
$ git checkout feature/1 -q
$ git push -f
-✓ Patch 696ec55 updated to revision [...]
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c merged
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- + 20aa5dd...954bcdb feature/1 -> patches/696ec5508494692899337afe6713fe1796d0315c (forced update)
+✓ Patch 43362c8 updated to revision [..]
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 merged
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ + 20aa5dd...954bcdb feature/1 -> patches/43362c8b437a0ce6798a762f3676e4dd68b67792 (forced update)
```
diff --git a/crates/radicle-cli/examples/rad-merge-no-ff.md b/crates/radicle-cli/examples/rad-merge-no-ff.md
index 39999cea80..f04ef0ffd0 100644
--- a/crates/radicle-cli/examples/rad-merge-no-ff.md
+++ b/crates/radicle-cli/examples/rad-merge-no-ff.md
@@ -4,8 +4,8 @@ First, let's create a patch.
$ git checkout -b feature/1 -q
$ git commit --allow-empty -q -m "First change"
$ git push rad HEAD:refs/patches
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -36,8 +36,8 @@ committer radicle <radicle@localhost> 1671125284 +0000
Finally, we push master and expect the patch to be merged.
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad master
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c merged
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 merged
✓ Canonical reference refs/heads/master updated to target commit 737a10cfa29111afeb0d43cf3545cee386b939ec
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..737a10c master -> master
```
diff --git a/crates/radicle-cli/examples/rad-merge-via-push.md b/crates/radicle-cli/examples/rad-merge-via-push.md
index d8d5e40e3a..5add745edc 100644
--- a/crates/radicle-cli/examples/rad-merge-via-push.md
+++ b/crates/radicle-cli/examples/rad-merge-via-push.md
@@ -7,8 +7,8 @@ $ git commit --allow-empty -m "First change"
```
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad HEAD:refs/patches
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
```
@@ -18,8 +18,8 @@ $ git commit --allow-empty -m "Second change"
```
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad HEAD:refs/patches
-✓ Patch 356f73863a8920455ff6e77cd9c805d68910551b opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 745487c5cd672f16b29297e8ed65d7f10cd70577 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -28,8 +28,8 @@ This creates some remote tracking branches for us:
```
$ git branch -r
rad/master
- rad/patches/356f73863a8920455ff6e77cd9c805d68910551b
- rad/patches/696ec5508494692899337afe6713fe1796d0315c
+ rad/patches/43362c8b437a0ce6798a762f3676e4dd68b67792
+ rad/patches/745487c5cd672f16b29297e8ed65d7f10cd70577
```
And some remote refs:
@@ -40,15 +40,15 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
- │ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
│ └── xyz.radicle.patch
- │ ├── 356f73863a8920455ff6e77cd9c805d68910551b
- │ └── 696ec5508494692899337afe6713fe1796d0315c
+ │ ├── 43362c8b437a0ce6798a762f3676e4dd68b67792
+ │ └── 745487c5cd672f16b29297e8ed65d7f10cd70577
├── heads
│ ├── master
│ └── patches
- │ ├── 356f73863a8920455ff6e77cd9c805d68910551b
- │ └── 696ec5508494692899337afe6713fe1796d0315c
+ │ ├── 43362c8b437a0ce6798a762f3676e4dd68b67792
+ │ └── 745487c5cd672f16b29297e8ed65d7f10cd70577
└── rad
├── id
├── root
@@ -68,10 +68,10 @@ When we push to `rad/master`, we automatically merge the patches:
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad master
-✓ Patch 356f73863a8920455ff6e77cd9c805d68910551b merged
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c merged
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 merged
+✓ Patch 745487c5cd672f16b29297e8ed65d7f10cd70577 merged
✓ Canonical reference refs/heads/master updated to target commit d6399c71702b40bae00825b3c444478d06b4e91c
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..d6399c7 master -> master
```
```
@@ -79,16 +79,16 @@ $ rad patch --merged
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────┤
-│ ✓ [ ... ] Second change alice (you) - daf349f +0 -0 now │
-│ ✓ [ ... ] First change alice (you) - 20aa5dd +0 -0 now │
+│ ✓ 43362c8 First change alice (you) - 20aa5dd +0 -0 now │
+│ ✓ 745487c Second change alice (you) - daf349f +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────╯
-$ rad patch show 696ec5508494692899337afe6713fe1796d0315c
+$ rad patch show 43362c8b437a0ce6798a762f3676e4dd68b67792
╭──────────────────────────────────────────────────────────╮
│ Title First change │
-│ Patch 696ec5508494692899337afe6713fe1796d0315c │
+│ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 │
│ Author alice (you) │
│ Head 20aa5dde6210796c3a2f04079b42316a31d02689 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1 │
│ Commits ahead 0, behind 2 │
@@ -96,16 +96,16 @@ $ rad patch show 696ec5508494692899337afe6713fe1796d0315c
├──────────────────────────────────────────────────────────┤
│ 20aa5dd First change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 696ec55 @ [.. ]..20aa5dd by alice (you) now │
+│ ● Revision 43362c8 @ [..]..20aa5dd by alice (you) now │
│ └─ ✓ merged by alice (you) │
╰──────────────────────────────────────────────────────────╯
-$ rad patch show 356f73863a8920455ff6e77cd9c805d68910551b
+$ rad patch show 745487c5cd672f16b29297e8ed65d7f10cd70577
╭──────────────────────────────────────────────────────────╮
│ Title Second change │
-│ Patch 356f73863a8920455ff6e77cd9c805d68910551b │
+│ Patch 745487c5cd672f16b29297e8ed65d7f10cd70577 │
│ Author alice (you) │
│ Head daf349ff76bedf48c5f292290b682ee7be0683cf │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/2 │
│ Commits ahead 0, behind 2 │
@@ -113,7 +113,7 @@ $ rad patch show 356f73863a8920455ff6e77cd9c805d68910551b
├──────────────────────────────────────────────────────────┤
│ daf349f Second change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 356f738 @ [.. ]..daf349f by alice (you) now │
+│ ● Revision 745487c @ [..]..daf349f by alice (you) now │
│ └─ ✓ merged by alice (you) │
╰──────────────────────────────────────────────────────────╯
```
@@ -133,10 +133,10 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
- │ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
│ └── xyz.radicle.patch
- │ ├── 356f73863a8920455ff6e77cd9c805d68910551b
- │ └── 696ec5508494692899337afe6713fe1796d0315c
+ │ ├── 43362c8b437a0ce6798a762f3676e4dd68b67792
+ │ └── 745487c5cd672f16b29297e8ed65d7f10cd70577
├── heads
│ └── master
└── rad
@@ -151,9 +151,9 @@ the first patch, even though they were pushed together.
``` (stderr) RAD_SOCKET=/dev/null
$ git reset --hard HEAD^
$ git push -f rad
-! Patch 356f73863a8920455ff6e77cd9c805d68910551b reverted at revision 356f738
+! Patch 745487c5cd672f16b29297e8ed65d7f10cd70577 reverted at revision 745487c
✓ Canonical reference refs/heads/master updated to target commit 20aa5dde6210796c3a2f04079b42316a31d02689
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ d6399c7...20aa5dd master -> master (forced update)
```
```
@@ -161,7 +161,7 @@ $ rad patch --all
╭─────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 356f738 Second change alice (you) - daf349f +0 -0 now │
-│ ✓ 696ec55 First change alice (you) - 20aa5dd +0 -0 now │
+│ ✓ 43362c8 First change alice (you) - 20aa5dd +0 -0 now │
+│ ● 745487c Second change alice (you) - daf349f +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-node.md b/crates/radicle-cli/examples/rad-node.md
index 8f7d8591f0..ab4aadb806 100644
--- a/crates/radicle-cli/examples/rad-node.md
+++ b/crates/radicle-cli/examples/rad-node.md
@@ -43,7 +43,7 @@ $ rad seed
╭───────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├───────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji heartwood allow followed │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G heartwood allow followed │
╰───────────────────────────────────────────────────────────────────╯
```
@@ -68,7 +68,7 @@ $ rad node routing
╭──────────────────────────────────────────────────────────────────────────────────────╮
│ RID NID │
├──────────────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
╰──────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -90,8 +90,8 @@ $ rad node stop
Note that if we unseed a repository, it is no longer part of our inventory:
```
-$ rad unseed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji removed
+$ rad unseed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G removed
$ rad node inventory
```
@@ -99,18 +99,18 @@ Likewise, if we seed a repository we don't have locally, it won't show up as
part of our inventory:
```
$ rad seed rad:z3trNYnLWS11cJWC6BbxDs5niGo82
-[...]
+[..]
$ rad node inventory
```
But if we start seeding the repository we have locally again, it'll show
up in our inventory:
```
-$ rad seed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Inventory updated with rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+$ rad seed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Inventory updated with rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
$ rad node inventory
-rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
Some commands also give us a hint if the node isn't running:
diff --git a/crates/radicle-cli/examples/rad-patch-ahead-behind.md b/crates/radicle-cli/examples/rad-patch-ahead-behind.md
index c9b2be25d5..3bdc0e0bb3 100644
--- a/crates/radicle-cli/examples/rad-patch-ahead-behind.md
+++ b/crates/radicle-cli/examples/rad-patch-ahead-behind.md
@@ -37,8 +37,8 @@ $ git log --graph --decorate --abbrev-commit --pretty=oneline --all
Then we create a patch from `feature/1`:
``` (stderr)
$ git push rad feature/1:refs/patches
-✓ Patch 217f050f8891def8fb863f7c0b4f85c89f97299d opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 0eb9ee630b38594e17f434ed17bb0679065b2ecd opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] feature/1 -> refs/patches
```
@@ -48,17 +48,17 @@ $ rad patch list
╭────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├────────────────────────────────────────────────────────────────────────────────┤
-│ ● 217f050 Add Alan alice (you) - 5c88a79 +1 -0 now │
+│ ● 0eb9ee6 Add Alan alice (you) - 5c88a79 +1 -0 now │
╰────────────────────────────────────────────────────────────────────────────────╯
```
When showing the patch, we see that it is `ahead 1, behind 1`, since master has
diverged by one commit:
```
-$ rad patch show -v -p 217f050
+$ rad patch show -v -p 0eb9ee6
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Add Alan │
-│ Patch 217f050f8891def8fb863f7c0b4f85c89f97299d │
+│ Patch 0eb9ee630b38594e17f434ed17bb0679065b2ecd │
│ Author alice (you) │
│ Head 5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7 │
│ Base f64fb2c8fe28f7c458c72ec8d700373924794943 │
@@ -69,7 +69,7 @@ $ rad patch show -v -p 217f050
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 5c88a79 Add Alan │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision 217f050f8891def8fb863f7c0b4f85c89f97299d with range f64fb2c8fe28f7c458c72ec8d700373924794943..5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7 by alice (you) now │
+│ ● Revision 0eb9ee630b38594e17f434ed17bb0679065b2ecd with range f64fb2c8fe28f7c458c72ec8d700373924794943..5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7 by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
commit 5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7
@@ -94,18 +94,18 @@ $ git checkout -q -b feature/2 feature/1
$ sed -i '$a Mel Farna' CONTRIBUTORS
$ git commit -a -q -m "Add Mel"
$ git push -o patch.message="Add Mel" rad HEAD:refs/patches
-✓ Patch e22ff008e2a0ed47262890d13263031d7555b555 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 29c888f25b6e647fb985812209f1a900dc01333a opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
When we look at the patch, we see that it has both commits, because this new
patch uses the same base as the previous patch:
```
-$ rad patch show -v e22ff008e2a0ed47262890d13263031d7555b555
+$ rad patch show -v 29c888f25b6e647fb985812209f1a900dc01333a
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Add Mel │
-│ Patch e22ff008e2a0ed47262890d13263031d7555b555 │
+│ Patch 29c888f25b6e647fb985812209f1a900dc01333a │
│ Author alice (you) │
│ Head 7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 │
│ Base f64fb2c8fe28f7c458c72ec8d700373924794943 │
@@ -117,7 +117,7 @@ $ rad patch show -v e22ff008e2a0ed47262890d13263031d7555b555
│ 7f63fcb Add Mel │
│ 5c88a79 Add Alan │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision e22ff008e2a0ed47262890d13263031d7555b555 with range f64fb2c8fe28f7c458c72ec8d700373924794943..7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 by alice (you) now │
+│ ● Revision 29c888f25b6e647fb985812209f1a900dc01333a with range f64fb2c8fe28f7c458c72ec8d700373924794943..7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -126,8 +126,8 @@ If we want to instead create a "stacked" patch, we can do so with the
``` (stderr)
$ git push -o patch.message="Add Mel #2" -o patch.base=HEAD^ rad HEAD:refs/patches
-✓ Patch a467ffa260c4fbe355b6fb550ba0c4956078717e opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 7bfdb801d676c78d604af10f89d341f7bc646b45 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -138,10 +138,10 @@ However, since the patch is still intended to be merged into `master`, we see
that it is still two commits ahead and one behind from `master`.
```
-$ rad patch show -v a467ffa260c4fbe355b6fb550ba0c4956078717e
+$ rad patch show -v 7bfdb801d676c78d604af10f89d341f7bc646b45
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Add Mel #2 │
-│ Patch a467ffa260c4fbe355b6fb550ba0c4956078717e │
+│ Patch 7bfdb801d676c78d604af10f89d341f7bc646b45 │
│ Author alice (you) │
│ Head 7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 │
│ Base 5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7 │
@@ -152,6 +152,6 @@ $ rad patch show -v a467ffa260c4fbe355b6fb550ba0c4956078717e
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 7f63fcb Add Mel │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision a467ffa260c4fbe355b6fb550ba0c4956078717e with range 5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7..7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 by alice (you) now │
+│ ● Revision 7bfdb801d676c78d604af10f89d341f7bc646b45 with range 5c88a79d75f5c2b4cc51ee6f163d2db91ee198d7..7f63fcbcf23fc39eea784c091ad3d20d7e4bd005 by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-change-base.md b/crates/radicle-cli/examples/rad-patch-change-base.md
index e7a55cdf94..e89beefc75 100644
--- a/crates/radicle-cli/examples/rad-patch-change-base.md
+++ b/crates/radicle-cli/examples/rad-patch-change-base.md
@@ -15,11 +15,11 @@ $ git commit -v -m "Define power requirements"
```
``` (stderr)
$ git push rad flux-capacitor-power
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] flux-capacitor-power -> flux-capacitor-power
$ git push rad -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch aa45913e757cacd46972733bddee5472c78fa32a opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -35,18 +35,18 @@ $ git commit --message "Add README, just for the fun"
```
``` (stderr)
$ git push rad -o patch.message="Add README, just for the fun" HEAD:refs/patches
-✓ Patch 183d343ab47d7fe18baf1b24b7209ad033d7fe5c opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch cf92361190b992fa4a3f603b848fb630bf5c55e0 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
Our second patch looks like the following:
```
-$ rad patch show 183d343ab47d7fe18baf1b24b7209ad033d7fe5c
+$ rad patch show cf92361190b992fa4a3f603b848fb630bf5c55e0
╭──────────────────────────────────────────────────────────╮
│ Title Add README, just for the fun │
-│ Patch 183d343ab47d7fe18baf1b24b7209ad033d7fe5c │
+│ Patch cf92361190b992fa4a3f603b848fb630bf5c55e0 │
│ Author alice (you) │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -58,7 +58,7 @@ $ rad patch show 183d343ab47d7fe18baf1b24b7209ad033d7fe5c
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 183d343 @ f2de534..27857ec by alice (you) now │
+│ ● Revision cf92361 @ f2de534..27857ec by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -67,18 +67,18 @@ commit `3e674d1` as part of this patch, so we create a new revision
with a new `base`:
```
-$ rad patch update 183d343 -b 3e674d1 -m "Whoops, forgot to set the base" --no-announce
-ebe76f9c2148eb595d7a745f82275786bf3458c3
+$ rad patch update cf92361 -b 3e674d1 -m "Whoops, forgot to set the base" --no-announce
+02e77b19af9aeba218c8abe480bbcced8541e160
```
Now, if we show the patch we can see the patch's base has changed and
we have a single commit:
```
-$ rad patch show 183d343
+$ rad patch show cf92361
╭──────────────────────────────────────────────────────────╮
│ Title Add README, just for the fun │
-│ Patch 183d343ab47d7fe18baf1b24b7209ad033d7fe5c │
+│ Patch cf92361190b992fa4a3f603b848fb630bf5c55e0 │
│ Author alice (you) │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
│ Base 3e674d1a1df90807e934f9ae5da2591dd6848a33 │
@@ -89,7 +89,7 @@ $ rad patch show 183d343
├──────────────────────────────────────────────────────────┤
│ 27857ec Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 183d343 @ f2de534..27857ec by alice (you) now │
-│ ↑ Revision ebe76f9 @ 3e674d1..27857ec by alice (you) now │
+│ ● Revision cf92361 @ f2de534..27857ec by alice (you) now │
+│ ↑ Revision 02e77b1 @ 3e674d1..27857ec by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-checkout-force.md b/crates/radicle-cli/examples/rad-patch-checkout-force.md
index d4b476cfd6..5ab3d15ddc 100644
--- a/crates/radicle-cli/examples/rad-patch-checkout-force.md
+++ b/crates/radicle-cli/examples/rad-patch-checkout-force.md
@@ -13,9 +13,9 @@ $ git commit -v -m "Define power requirements"
``` ~alice (stderr)
$ git push rad -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch aa45913e757cacd46972733bddee5472c78fa32a opened
+✓ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 opened
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -24,12 +24,12 @@ On the other end, Bob uses `rad patch checkout` to view the patch:
``` ~bob
$ cd heartwood
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-$ rad patch checkout aa45913 --name alice-init
-✓ Switched to branch alice-init at revision aa45913
-✓ Branch alice-init setup to track rad/patches/aa45913e757cacd46972733bddee5472c78fa32a
+$ rad patch checkout 26ba061 --name alice-init
+✓ Switched to branch alice-init at revision 26ba061
+✓ Branch alice-init setup to track rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
Meanwhile, we may see some more changes that we need to make, so we
@@ -46,28 +46,28 @@ $ git commit --message "Add README, just for the fun"
``` ~alice (stderr)
$ git push rad -o patch.message="Add README, just for the fun"
-✓ Patch aa45913 updated to revision 3156bed9d64d4675d6cf56612d217fc5f4e8a53a
-To compare against your previous revision aa45913, run:
+✓ Patch 26ba061 updated to revision 32a5d05e0be58807fba749f320114cefac3e2d2e
+To compare against your previous revision 26ba061, run:
- git range-diff f2de534[..] 3e674d1[..] 27857ec[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 3e674d1a1df90807e934f9ae5da2591dd6848a33 27857ec9eb04c69cacab516e8bf4b5fd36090f66
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 3e674d1..27857ec flux-capacitor-power -> patches/aa45913e757cacd46972733bddee5472c78fa32a
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 3e674d1..27857ec flux-capacitor-power -> patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
Bob fetches these new changes and can see their branch is now behind:
``` ~bob (stderr)
$ git fetch rad
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
- 3e674d1..27857ec patches/aa45913e757cacd46972733bddee5472c78fa32a -> rad/patches/aa45913e757cacd46972733bddee5472c78fa32a
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+ 3e674d1..27857ec patches/26ba0615c6e911344ee61d53241a2903c5bf8623 -> rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
``` ~bob
$ git status
On branch alice-init
-Your branch is behind 'rad/patches/aa45913e757cacd46972733bddee5472c78fa32a' by 1 commit, and can be fast-forwarded.
+Your branch is behind 'rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
@@ -79,17 +79,17 @@ overwrite any changes. Bob can choose to use the `--force` (`-f`) flag to
ensure that they are looking at the latest changes:
``` ~bob (fail)
-$ rad patch checkout aa45913 --name alice-init
+$ rad patch checkout 26ba061 --name alice-init
✗ Performing checkout… <canceled>
✗ Error: branch 'alice-init' already exists (use `--force` to overwrite)
```
``` ~bob
-$ rad patch checkout aa45913 -f --name alice-init
-✓ Switched to branch alice-init at revision 3156bed
+$ rad patch checkout 26ba061 -f --name alice-init
+✓ Switched to branch alice-init at revision 32a5d05
$ git status
On branch alice-init
-Your branch is up to date with 'rad/patches/aa45913e757cacd46972733bddee5472c78fa32a'.
+Your branch is up to date with 'rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623'.
nothing to commit, working tree clean
```
diff --git a/crates/radicle-cli/examples/rad-patch-checkout-revision.md b/crates/radicle-cli/examples/rad-patch-checkout-revision.md
index f045d3abd4..ced108bcb5 100644
--- a/crates/radicle-cli/examples/rad-patch-checkout-revision.md
+++ b/crates/radicle-cli/examples/rad-patch-checkout-revision.md
@@ -5,7 +5,7 @@ So first, let's add another change to the patch and a `LICENSE` file.
$ touch LICENSE
$ git add LICENSE
$ git commit --message "Add LICENSE, just for the business"
-[patch/aa45913 639f44a] Add LICENSE, just for the business
+[patch/26ba061 639f44a] Add LICENSE, just for the business
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 LICENSE
$ git push rad -o patch.message="Add LICENSE, just for the business"
@@ -14,15 +14,15 @@ $ git push rad -o patch.message="Add LICENSE, just for the business"
We can see the list of revisions of the patch by `show`ing it:
```
-$ rad patch show aa45913
+$ rad patch show 26ba061
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch aa45913e757cacd46972733bddee5472c78fa32a │
+│ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 │
│ Author alice (you) │
│ Head 639f44a25145a37f747f3c84265037a9461e44c5 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
-│ Branches patch/aa45913 │
+│ Branches patch/26ba061 │
│ Commits ahead 3, behind 0 │
│ Status open │
│ │
@@ -32,20 +32,20 @@ $ rad patch show aa45913
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision aa45913 @ [.. ]..3e674d1 by alice (you) now │
-│ ↑ Revision 3156bed @ [.. ]..27857ec by alice (you) now │
-│ ↑ Revision 2f5324f @ [.. ]..639f44a by alice (you) now │
+│ ● Revision 26ba061 @ [..]..3e674d1 by alice (you) now │
+│ ↑ Revision 32a5d05 @ f2de534..27857ec by alice (you) now │
+│ ↑ Revision 3d2355d @ f2de534..639f44a by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
So, let's checkout the previous revision, `0c0942e2`:
```
-$ rad patch checkout aa45913 --revision 3156bed9d64d4675d6cf56612d217fc5f4e8a53a -f
-✓ Switched to branch patch/aa45913 at revision 3156bed
+$ rad patch checkout 26ba061 --revision 32a5d05e0be58807fba749f320114cefac3e2d2e -f
+✓ Switched to branch patch/26ba061 at revision 32a5d05
```
-And we can confirm that the current commit corresponds to `27857ec`:
+And we can confirm that the current commit corresponds to `3032c7f`:
```
$ git rev-parse HEAD
diff --git a/crates/radicle-cli/examples/rad-patch-checkout.md b/crates/radicle-cli/examples/rad-patch-checkout.md
index 044e6c26f5..e48ca577f0 100644
--- a/crates/radicle-cli/examples/rad-patch-checkout.md
+++ b/crates/radicle-cli/examples/rad-patch-checkout.md
@@ -22,17 +22,17 @@ Once the code is ready, we open (or create) a patch with our changes for the pro
``` (stderr)
$ git push rad -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch aa45913e757cacd46972733bddee5472c78fa32a opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
Now, let's checkout the patch that we just created:
```
-$ rad patch checkout aa45913e757cacd46972733bddee5472c78fa32a
-✓ Switched to branch patch/aa45913 at revision aa45913
-✓ Branch patch/aa45913 setup to track rad/patches/aa45913e757cacd46972733bddee5472c78fa32a
+$ rad patch checkout 26ba0615c6e911344ee61d53241a2903c5bf8623
+✓ Switched to branch patch/26ba061 at revision 26ba061
+✓ Branch patch/26ba061 setup to track rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
Note that `rad patch checkout` can be used to switch to the patch branch
@@ -40,8 +40,8 @@ as long as we haven't made changes to it.
```
$ git checkout master -q
-$ rad patch checkout aa45913
-✓ Switched to branch patch/aa45913 at revision aa45913
+$ rad patch checkout 26ba061
+✓ Switched to branch patch/26ba061 at revision 26ba061
```
Now, let's add a README too!
@@ -50,7 +50,7 @@ Now, let's add a README too!
$ touch README.md
$ git add README.md
$ git commit --message "Add README, just for the fun"
-[patch/aa45913 27857ec] Add README, just for the fun
+[patch/26ba061 27857ec] Add README, just for the fun
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
```
@@ -59,11 +59,11 @@ We can now finish off the update:
``` (stderr)
$ git push rad -o patch.message="Add README, just for the fun"
-✓ Patch aa45913 updated to revision 3156bed9d64d4675d6cf56612d217fc5f4e8a53a
-To compare against your previous revision aa45913, run:
+✓ Patch 26ba061 updated to revision 32a5d05e0be58807fba749f320114cefac3e2d2e
+To compare against your previous revision 26ba061, run:
- git range-diff f2de534[..] 3e674d1[..] 27857ec[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 3e674d1a1df90807e934f9ae5da2591dd6848a33 27857ec9eb04c69cacab516e8bf4b5fd36090f66
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 3e674d1..27857ec patch/aa45913 -> patches/aa45913e757cacd46972733bddee5472c78fa32a
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 3e674d1..27857ec patch/26ba061 -> patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
diff --git a/crates/radicle-cli/examples/rad-patch-delete.md b/crates/radicle-cli/examples/rad-patch-delete.md
index 47bcecec7f..1d6af2272f 100644
--- a/crates/radicle-cli/examples/rad-patch-delete.md
+++ b/crates/radicle-cli/examples/rad-patch-delete.md
@@ -10,32 +10,32 @@ $ git commit -m "Introduce license"
``` ~alice (stderr)
$ git push rad -o patch.draft -o patch.message="Define LICENSE for project" HEAD:refs/patches
-✓ Patch 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b drafted
+✓ Patch 482eff7804f958efeef1cb63f511f2ed1431f742 drafted
✓ Synced with 2 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
``` ~bob
$ cd heartwood
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
-$ rad patch comment 6c61ef1 -m "I think we should use MIT"
+$ rad patch comment 482eff7 -m "I think we should use MIT"
╭───────────────────────────╮
-│ bob (you) now 833db19 │
+│ bob (you) now 9963ada │
│ I think we should use MIT │
╰───────────────────────────╯
✓ Synced with 2 seed(s)
```
``` ~alice
-$ rad patch show 6c61ef1 -v
+$ rad patch show 482eff7 -v
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Define LICENSE for project │
-│ Patch 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b │
+│ Patch 482eff7804f958efeef1cb63f511f2ed1431f742 │
│ Author alice (you) │
│ Head 717c900ec17735639587325e0fd9fe09991c9edd │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -46,14 +46,14 @@ $ rad patch show 6c61ef1 -v
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 717c900 Introduce license │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice (you) now │
+│ ● Revision 482eff7804f958efeef1cb63f511f2ed1431f742 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice (you) now │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ bob z6Mkt67…v4N1tRk now 833db19 │
+│ bob z6Mkt67…v4N1tRk now 9963ada │
│ I think we should use MIT │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
-$ rad patch comment 6c61ef1 --reply-to 833db19 -m "Thanks, I'll add it!"
+$ rad patch comment 482eff7 --reply-to 9963ada -m "Thanks, I'll add it!"
╭─────────────────────────╮
-│ alice (you) now 1803a38 │
+│ alice (you) now 294ce2f │
│ Thanks, I'll add it! │
╰─────────────────────────╯
✓ Synced with 2 seed(s)
@@ -70,24 +70,24 @@ $ git commit -am "Add MIT License"
``` ~alice (stderr)
$ git push -f
-✓ Patch 6c61ef1 updated to revision 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3
-To compare against your previous revision 6c61ef1, run:
+✓ Patch 482eff7 updated to revision 68c388e97fa5c63b7a843861bc23bd7ebfcd84ba
+To compare against your previous revision 482eff7, run:
- git range-diff f2de534[..] 717c900[..] 1cc8cd9[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 717c900ec17735639587325e0fd9fe09991c9edd 1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e
✓ Synced with 2 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 717c900..1cc8cd9 prepare-license -> patches/6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 717c900..1cc8cd9 prepare-license -> patches/482eff7804f958efeef1cb63f511f2ed1431f742
```
``` ~bob
-$ rad patch review 6c61ef1 --accept -m "LGTM!"
-✓ Patch 6c61ef1 accepted
+$ rad patch review 482eff7 --accept -m "LGTM!"
+✓ Patch 482eff7 accepted
✓ Synced with 2 seed(s)
-$ rad patch show 6c61ef1 -v
+$ rad patch show 482eff7 -v
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Define LICENSE for project │
-│ Patch 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b │
+│ Patch 482eff7804f958efeef1cb63f511f2ed1431f742 │
│ Author alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ Head 1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -98,22 +98,22 @@ $ rad patch show 6c61ef1 -v
│ 1cc8cd9 Add MIT License │
│ 717c900 Introduce license │
├─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi now │
-│ ↑ Revision 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e by alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi now │
+│ ● Revision 482eff7804f958efeef1cb63f511f2ed1431f742 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi now │
+│ ↑ Revision 68c388e97fa5c63b7a843861bc23bd7ebfcd84ba with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e by alice z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi now │
│ └─ ✓ accepted by bob (you) now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
``` ~bob
-$ rad patch delete 6c61ef1
+$ rad patch delete 482eff7
✓ Synced with 2 seed(s)
```
``` ~alice
-$ rad patch show 6c61ef1 -v
+$ rad patch show 482eff7 -v
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Define LICENSE for project │
-│ Patch 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b │
+│ Patch 482eff7804f958efeef1cb63f511f2ed1431f742 │
│ Author alice (you) │
│ Head 1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -125,8 +125,8 @@ $ rad patch show 6c61ef1 -v
│ 1cc8cd9 Add MIT License │
│ 717c900 Introduce license │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision 6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice (you) now │
-│ ↑ Revision 93915b9afa94a9dc4f52f12cdf077d4613ea3eb3 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e by alice (you) now │
+│ ● Revision 482eff7804f958efeef1cb63f511f2ed1431f742 with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..717c900ec17735639587325e0fd9fe09991c9edd by alice (you) now │
+│ ↑ Revision 68c388e97fa5c63b7a843861bc23bd7ebfcd84ba with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..1cc8cd9de8ccc44b4fe3876f2dbd2cd1cf9ddc0e by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -134,11 +134,11 @@ If Alice also decides to delete the patch, then any seeds that have synced with
Alice should no longer have the patch:
``` ~alice
-$ rad patch delete 6c61ef1
+$ rad patch delete 482eff7
✓ Synced with 2 seed(s)
```
``` ~seed (fails)
-$ rad patch show --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji 6c61ef1 -v
-✗ Error: Patch `6c61ef1716ad8a5c11e04dd7a3fec51e01fba70b` not found
+$ rad patch show --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G 482eff7 -v
+✗ Error: Patch `482eff7804f958efeef1cb63f511f2ed1431f742` not found
```
diff --git a/crates/radicle-cli/examples/rad-patch-detached-head.md b/crates/radicle-cli/examples/rad-patch-detached-head.md
index ab0c3f8e1d..7904bc7aa9 100644
--- a/crates/radicle-cli/examples/rad-patch-detached-head.md
+++ b/crates/radicle-cli/examples/rad-patch-detached-head.md
@@ -30,10 +30,10 @@ Now, we can create a commit on top of this and create a patch, as usual:
``` (stderr) RAD_HINT=1
$ git commit -a -m "Add things" -q --allow-empty
$ git push -o patch.message="Add things #1" -o patch.message="See commits for details." rad HEAD:refs/patches
-✓ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened
+✓ Patch 4e0b866a7ac15131ad472888528ae0e048ee952f opened
hint: offline push, your node is not running
hint: to sync with the network, run `rad node start`
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
diff --git a/crates/radicle-cli/examples/rad-patch-diff.md b/crates/radicle-cli/examples/rad-patch-diff.md
index 6504658f47..de6b8366eb 100644
--- a/crates/radicle-cli/examples/rad-patch-diff.md
+++ b/crates/radicle-cli/examples/rad-patch-diff.md
@@ -10,7 +10,7 @@ $ git commit -m "Add README" -q
$ git push rad HEAD:refs/patches
```
```
-$ rad patch diff 147309e
+$ rad patch diff a0b50ac
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..980a0d5
@@ -31,7 +31,7 @@ $ git commit --amend -q
$ git push -f
```
```
-$ rad patch diff 147309e
+$ rad patch diff a0b50ac
diff --git a/RADICLE.md b/RADICLE.md
new file mode 100644
index 0000000..e517184
@@ -52,7 +52,7 @@ Buf if we only want to see the changes from the first revision, we can do that
too.
```
-$ rad patch diff 147309e --revision 147309e
+$ rad patch diff a0b50ac --revision a0b50ac
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..980a0d5
diff --git a/crates/radicle-cli/examples/rad-patch-draft.md b/crates/radicle-cli/examples/rad-patch-draft.md
index adc502ec8d..ae97490412 100644
--- a/crates/radicle-cli/examples/rad-patch-draft.md
+++ b/crates/radicle-cli/examples/rad-patch-draft.md
@@ -9,21 +9,21 @@ To open a patch in draft mode, we use the `--draft` option:
``` (stderr)
$ git push -o patch.draft -o patch.message="Nothing yet" rad HEAD:refs/patches
-✓ Patch 97e18f8598237a396a1c0ac1509c89028e666c97 drafted
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch b599f894b2b409d800e74e8a9b9d817faff80e9a drafted
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
We can confirm it's a draft by running `show`:
```
-$ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
+$ rad patch show b599f894b2b409d800e74e8a9b9d817faff80e9a
╭──────────────────────────────────────────────────────────╮
│ Title Nothing yet │
-│ Patch 97e18f8598237a396a1c0ac1509c89028e666c97 │
+│ Patch b599f894b2b409d800e74e8a9b9d817faff80e9a │
│ Author alice (you) │
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches cloudhead/draft │
│ Commits ahead 1, behind 0 │
@@ -31,24 +31,24 @@ $ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
├──────────────────────────────────────────────────────────┤
│ 2a46583 Nothing to see here.. │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 97e18f8 @ [.. ]..2a46583 by alice (you) now │
+│ ● Revision b599f89 @ [..]..2a46583 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
Once the patch is ready for review, we can use the `ready` command:
```
-$ rad patch ready 97e18f8598237a396a1c0ac1509c89028e666c97 --no-announce
+$ rad patch ready b599f894b2b409d800e74e8a9b9d817faff80e9a --no-announce
```
```
-$ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
+$ rad patch show b599f894b2b409d800e74e8a9b9d817faff80e9a
╭──────────────────────────────────────────────────────────╮
│ Title Nothing yet │
-│ Patch 97e18f8598237a396a1c0ac1509c89028e666c97 │
+│ Patch b599f894b2b409d800e74e8a9b9d817faff80e9a │
│ Author alice (you) │
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches cloudhead/draft │
│ Commits ahead 1, behind 0 │
@@ -56,7 +56,7 @@ $ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
├──────────────────────────────────────────────────────────┤
│ 2a46583 Nothing to see here.. │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 97e18f8 @ [.. ]..2a46583 by alice (you) now │
+│ ● Revision b599f89 @ [..]..2a46583 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -64,14 +64,14 @@ If for whatever reason, it needed to go back into draft mode, we could use
the `--undo` flag:
```
-$ rad patch ready --undo 97e18f8598237a396a1c0ac1509c89028e666c97 --no-announce
-$ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
+$ rad patch ready --undo b599f894b2b409d800e74e8a9b9d817faff80e9a --no-announce
+$ rad patch show b599f894b2b409d800e74e8a9b9d817faff80e9a
╭──────────────────────────────────────────────────────────╮
│ Title Nothing yet │
-│ Patch 97e18f8598237a396a1c0ac1509c89028e666c97 │
+│ Patch b599f894b2b409d800e74e8a9b9d817faff80e9a │
│ Author alice (you) │
│ Head 2a465832b5a76abe25be44a3a5d224bbd7741ba7 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches cloudhead/draft │
│ Commits ahead 1, behind 0 │
@@ -79,6 +79,6 @@ $ rad patch show 97e18f8598237a396a1c0ac1509c89028e666c97
├──────────────────────────────────────────────────────────┤
│ 2a46583 Nothing to see here.. │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 97e18f8 @ [.. ]..2a46583 by alice (you) now │
+│ ● Revision b599f89 @ [..]..2a46583 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-edit.md b/crates/radicle-cli/examples/rad-patch-edit.md
index a2cd09d3dc..fac6a333c5 100644
--- a/crates/radicle-cli/examples/rad-patch-edit.md
+++ b/crates/radicle-cli/examples/rad-patch-edit.md
@@ -16,8 +16,8 @@ $ git commit --message "Add README, just for the fun"
``` (stderr)
$ git push rad -o patch.message="Add README, just for the fun" HEAD:refs/patches
-✓ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -32,25 +32,25 @@ $ git commit -v -m "Define the LICENSE"
``` (stderr)
$ git push -f -o patch.message="Add License"
-✓ Patch 89f7afb updated to revision 5d78dd5376453e25df5988ec86951c99cb73742c
-To compare against your previous revision 89f7afb, run:
+✓ Patch f36ce41 updated to revision 66230c3d87c5c444803e7d012a710013505dcdb9
+To compare against your previous revision f36ce41, run:
- git range-diff f2de534[..] 03c02af[..] 8945f61[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 03c02af4b12a593d17a06d38fae50a57fc3c339a 8945f6189adf027892c85ac57f7e9341049c2537
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 03c02af..8945f61 changes -> patches/89f7afb1511b976482b21f6b2f39aef7f4fb88a2
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 03c02af..8945f61 changes -> patches/f36ce41ee8d55d3723ad65ad39741391f9bed979
```
Let's look at the patch, to see what it looks like before editing it:
```
-$ rad patch show 89f7afb
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add README, just for the fun │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches changes │
│ Commits ahead 2, behind 0 │
@@ -59,8 +59,8 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ [.. ]..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ [.. ]..8945f61 by alice (you) now │
+│ ● Revision f36ce41 @ [..]..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ [..]..8945f61 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -68,14 +68,14 @@ We can change the title and description of the patch itself by using a
multi-line message (using two `--message` options here):
```
-$ rad patch edit 89f7afb --message "Add Metadata" --message "Add README & LICENSE" --no-announce
-$ rad patch show 89f7afb
+$ rad patch edit f36ce41 --message "Add Metadata" --message "Add README & LICENSE" --no-announce
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add Metadata │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches changes │
│ Commits ahead 2, behind 0 │
@@ -86,8 +86,8 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ [.. ]..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ [.. ]..8945f61 by alice (you) now │
+│ ● Revision f36ce41 @ [..]..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ [..]..8945f61 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -98,14 +98,14 @@ If we want to change a specific revision's description, we can use the
`--revision` option:
```
-$ rad patch edit 89f7afb --revision 5d78dd5 --message "Changes: Adds LICENSE file" --no-announce
-$ rad patch show 89f7afb
+$ rad patch edit f36ce41 --revision 66230c3 --message "Changes: Adds LICENSE file" --no-announce
+$ rad patch show f36ce41
╭──────────────────────────────────────────────────────────╮
│ Title Add Metadata │
-│ Patch 89f7afb1511b976482b21f6b2f39aef7f4fb88a2 │
+│ Patch f36ce41ee8d55d3723ad65ad39741391f9bed979 │
│ Author alice (you) │
│ Head 8945f6189adf027892c85ac57f7e9341049c2537 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches changes │
│ Commits ahead 2, behind 0 │
@@ -116,8 +116,8 @@ $ rad patch show 89f7afb
│ 8945f61 Define the LICENSE │
│ 03c02af Add README, just for the fun │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 89f7afb @ [.. ]..03c02af by alice (you) now │
-│ ↑ Revision 5d78dd5 @ [.. ]..8945f61 by alice (you) now │
+│ ● Revision f36ce41 @ [..]..03c02af by alice (you) now │
+│ ↑ Revision 66230c3 @ [..]..8945f61 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-fetch-1.md b/crates/radicle-cli/examples/rad-patch-fetch-1.md
index 28fdc9fc8e..e1ee4f23f7 100644
--- a/crates/radicle-cli/examples/rad-patch-fetch-1.md
+++ b/crates/radicle-cli/examples/rad-patch-fetch-1.md
@@ -20,9 +20,9 @@ $ git fetch --all
Fetching rad
Fetching alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ cat .git/FETCH_HEAD
-f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-7461703ce0fda972df450d071d1d3702057a6352 not-for-merge branch 'alice/1' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
-f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+7461703ce0fda972df450d071d1d3702057a6352 not-for-merge branch 'alice/1' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
$ git merge FETCH_HEAD
Already up to date.
$ git rev-parse master
diff --git a/crates/radicle-cli/examples/rad-patch-fetch-2.md b/crates/radicle-cli/examples/rad-patch-fetch-2.md
index a9392665cc..92e310fc68 100644
--- a/crates/radicle-cli/examples/rad-patch-fetch-2.md
+++ b/crates/radicle-cli/examples/rad-patch-fetch-2.md
@@ -12,7 +12,7 @@ $ git push rad -o patch.message="Changes" HEAD:refs/patches
$ git checkout master -q
$ git branch -D alice/1 -q
$ git update-ref -d refs/remotes/rad/alice/1
-$ git update-ref -d refs/remotes/rad/patches/5e2dedcc5d515fcbc1cca483d3376609fe889bfb
+$ git update-ref -d refs/remotes/rad/patches/1593312ce7ddd0258d5d1256bf06edceb592c527
$ git gc --prune=now
$ git branch -r
rad/master
@@ -23,5 +23,5 @@ $ git pull
Already up to date.
$ git branch -r
rad/master
- rad/patches/5e2dedcc5d515fcbc1cca483d3376609fe889bfb
+ rad/patches/1593312ce7ddd0258d5d1256bf06edceb592c527
```
diff --git a/crates/radicle-cli/examples/rad-patch-jj.md b/crates/radicle-cli/examples/rad-patch-jj.md
index 9c131dc828..25a765f282 100644
--- a/crates/radicle-cli/examples/rad-patch-jj.md
+++ b/crates/radicle-cli/examples/rad-patch-jj.md
@@ -38,8 +38,8 @@ Git to push.
``` (stderr)
$ git push rad -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch 1e31055ed3c41a48f2a71ba5317feb863b089700 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch c24d401043fbeae85d508f88b07b9cc3f4c646b3 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -50,7 +50,7 @@ $ rad patch
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 1e31055 Define power requirements alice (you) - a6ea7b7 +0 -0 now │
+│ ● c24d401 Define power requirements alice (you) - a6ea7b7 +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -61,10 +61,10 @@ $ jj bookmark create flux-capacitor-power
```
```
-$ rad patch show 1e31055 -p
+$ rad patch show c24d401 -p
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch 1e31055[.. ] │
+│ Patch c24d401[.. ] │
│ Author alice (you) │
│ Head a6ea7b7[.. ] │
│ Base f2de534[.. ] │
@@ -76,7 +76,7 @@ $ rad patch show 1e31055 -p
├──────────────────────────────────────────────────────────┤
│ a6ea7b7 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 1e31055 @ [.. ]..a6ea7b7 by alice (you) now │
+│ ● Revision c24d401 @ [.. ]..a6ea7b7 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
commit a6ea7b7[..]
diff --git a/crates/radicle-cli/examples/rad-patch-magic-push.md b/crates/radicle-cli/examples/rad-patch-magic-push.md
index 2fa569dc51..0847c184f1 100644
--- a/crates/radicle-cli/examples/rad-patch-magic-push.md
+++ b/crates/radicle-cli/examples/rad-patch-magic-push.md
@@ -3,7 +3,7 @@
First, we update the identity document to add a canonical reference rule for a new `accepted` branch, allowing delegates to merge into it.
```
-$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
+$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
[..]
```
@@ -21,8 +21,8 @@ $ git commit --allow-empty -m "Initialize accepted branch"
``` (stderr)
$ git push rad accepted
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] accepted -> accepted
```
@@ -38,20 +38,20 @@ Pushing to the magic reference:
``` (stderr)
$ git push rad HEAD:refs/for/accepted
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/for/accepted
```
We can see the patch is open:
```
-$ rad patch show 01dad54
+$ rad patch show 9df700a
╭──────────────────────────────────────────────────────────╮
│ Title Initialize accepted branch │
-│ Patch 01dad54873ada4efa61541e7d90702266d5ced89 │
+│ Patch 9df700a8f5520e7932eac90e76209f7b8d52d8d0 │
│ Author alice (you) │
│ Head 46fd342edc149468ec08b0b25291083aa05d4449 │
-│ Base [.. ] │
+│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
│ Target accepted │
│ Branches feature/1 │
│ Commits ahead 1, behind 0 │
@@ -62,13 +62,13 @@ $ rad patch show 01dad54
│ 46fd342 Add new feature │
│ f9a3b89 Initialize accepted branch │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 01dad54 @ f2de534..46fd342 by alice (you) now │
+│ ● Revision 9df700a @ f2de534..46fd342 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
$ rad patch list --open
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● [.. ] Initialize accepted branch alice (you) - [.. ] +0 -0 now │
+│ ● [..] Initialize accepted branch alice (you) - [..] +0 -0 now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -87,22 +87,22 @@ Fast-forward
``` (stderr)
$ git push rad accepted
-✓ Patch [..] merged
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- [..]..[..] accepted -> accepted
+✓ Patch 9df700a8f5520e7932eac90e76209f7b8d52d8d0 merged
+✓ Canonical reference refs/heads/accepted updated to target commit 46fd342edc149468ec08b0b25291083aa05d4449
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f9a3b89..46fd342 accepted -> accepted
```
We can now verify that the patch has been successfully marked as merged:
```
-$ rad patch show 01dad54
+$ rad patch show 9df700a
╭──────────────────────────────────────────────────────────╮
│ Title Initialize accepted branch │
-│ Patch 01dad54873ada4efa61541e7d90702266d5ced89 │
+│ Patch 9df700a8f5520e7932eac90e76209f7b8d52d8d0 │
│ Author alice (you) │
│ Head 46fd342edc149468ec08b0b25291083aa05d4449 │
-│ Base [.. ] │
+│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
│ Target accepted │
│ Branches accepted, feature/1 │
│ Commits up to date │
@@ -113,14 +113,14 @@ $ rad patch show 01dad54
│ 46fd342 Add new feature │
│ f9a3b89 Initialize accepted branch │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 01dad54 @ f2de534..46fd342 by alice (you) now │
+│ ● Revision 9df700a @ f2de534..46fd342 by alice (you) now │
│ └─ ✓ merged by alice (you) │
╰──────────────────────────────────────────────────────────╯
$ rad patch list --merged
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ✓ [.. ] Initialize accepted branch alice (you) - [.. ] +0 -0 now │
+│ ✓ 9df700a Initialize accepted branch alice (you) - 46fd342 +0 -0 now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -129,7 +129,7 @@ Alternative, attempting to provide conflicting targets fails:
``` (fail) (stderr)
$ git push -o patch.target=master rad HEAD:refs/for/accepted
error: conflicting merge targets: push option 'refs/heads/master' and magic ref 'refs/heads/accepted' specified
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
```
However, if the push option and the magic ref match, it succeeds:
@@ -142,14 +142,14 @@ $ git commit -m "Add another feature" --allow-empty -q
``` (stderr)
$ git push -o patch.target=accepted rad HEAD:refs/for/accepted
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/for/accepted
```
```
-$ rad patch show 965855f
+$ rad patch show b48e977
╭──────────────────────────────────────────────────────────╮
│ Title Initialize accepted branch │
-│ Patch 965855f69bc5a86f7e1787ed80cd065013b6504c │
+│ Patch b48e97770764ce5aaa679677bbdf878200cd3d57 │
│ Author alice (you) │
│ Head 7e6814e99fe7084a213faeb69ca1eacc26935e3c │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -167,7 +167,7 @@ $ rad patch show 965855f
│ 46fd342 Add new feature │
│ f9a3b89 Initialize accepted branch │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 965855f @ f2de534..7e6814e by alice (you) now │
+│ ● Revision b48e977 @ f2de534..7e6814e by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -180,17 +180,17 @@ $ git commit -m "Add a third feature" --allow-empty -q
``` (stderr)
$ git push rad HEAD:refs/for/refs/heads/accepted
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/for/refs/heads/accepted
```
This will create a third feature branch and verify that pushing to `refs/for/refs/heads/accepted` successfully opens a patch.
```
-$ rad patch show c846bb5 -v
+$ rad patch show 32fd5b5 -v
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Title Initialize accepted branch │
-│ Patch c846bb5f8298802e8de589174549d78c1d9aa00f │
+│ Patch 32fd5b5331af54415458e3d7d966713c87765b1d │
│ Author alice (you) │
│ Head 99c1d5a04c17ba854f1f4d59985c980c0faf16e7 │
│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
@@ -212,6 +212,6 @@ $ rad patch show c846bb5 -v
│ 46fd342 Add new feature │
│ f9a3b89 Initialize accepted branch │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● Revision c846bb5f8298802e8de589174549d78c1d9aa00f with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..99c1d5a04c17ba854f1f4d59985c980c0faf16e7 by alice (you) now │
+│ ● Revision 32fd5b5331af54415458e3d7d966713c87765b1d with range f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354..99c1d5a04c17ba854f1f4d59985c980c0faf16e7 by alice (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-merge-draft.md b/crates/radicle-cli/examples/rad-patch-merge-draft.md
index d36e67146e..262c1a3634 100644
--- a/crates/radicle-cli/examples/rad-patch-merge-draft.md
+++ b/crates/radicle-cli/examples/rad-patch-merge-draft.md
@@ -4,8 +4,8 @@ Let's start by creating a draft patch.
$ git checkout -b feature/1 -q
$ git commit --allow-empty -q -m "First change"
$ git push -o patch.draft rad HEAD:refs/patches
-✓ Patch 8dfb4dcafc4346158c8160410dd3f2b0616ad4fe drafted
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 556e4968ab018cb351a64bca782c4548f98d7493 drafted
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -13,8 +13,8 @@ To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkE
$ git checkout master -q
$ git merge feature/1
$ git push rad master
-✓ Patch 8dfb4dcafc4346158c8160410dd3f2b0616ad4fe merged
+✓ Patch 556e4968ab018cb351a64bca782c4548f98d7493 merged
✓ Canonical reference refs/heads/master updated to target commit 20aa5dde6210796c3a2f04079b42316a31d02689
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..20aa5dd master -> master
```
diff --git a/crates/radicle-cli/examples/rad-patch-merge-into-canonical-ref-branch.md b/crates/radicle-cli/examples/rad-patch-merge-into-canonical-ref-branch.md
index 26180d82d6..87eec3b753 100644
--- a/crates/radicle-cli/examples/rad-patch-merge-into-canonical-ref-branch.md
+++ b/crates/radicle-cli/examples/rad-patch-merge-into-canonical-ref-branch.md
@@ -3,7 +3,7 @@
First, we update the identity document to add a canonical reference rule for a new `accepted` branch, allowing delegates to merge into it.
```
-$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
+$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
[..]
```
@@ -21,8 +21,8 @@ $ git commit --allow-empty -m "Initialize accepted branch"
``` (stderr)
$ git push rad accepted
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] accepted -> accepted
```
@@ -45,7 +45,7 @@ $ git commit -m "Add new feature"
``` (stderr)
$ git push -o patch.message="Add new feature" -o patch.target="refs/heads/accepted" rad HEAD:refs/patches
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -56,7 +56,7 @@ $ rad patch
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ● [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ● [..] Add new feature alice (you) - [..] +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -78,10 +78,10 @@ Fast-forward
``` (stderr)
$ git push rad accepted
-✓ Patch [..] merged
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- [..]..[..] accepted -> accepted
+✓ Patch 38592f91ee06aeb38c88a5352ca4254accff3591 merged
+✓ Canonical reference refs/heads/accepted updated to target commit 27acd3b208662f374b34cd4c599f3628c9e42b80
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f9a3b89..27acd3b accepted -> accepted
```
Finally, we verify that the patch has been successfully marked as merged, even though it wasn't merged into the default branch.
@@ -91,6 +91,6 @@ $ rad patch list --merged
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ✓ [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ✓ 38592f9 Add new feature alice (you) - 27acd3b +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-merge-on-first-push.md b/crates/radicle-cli/examples/rad-patch-merge-on-first-push.md
index efeb6b72d7..5ba1372a77 100644
--- a/crates/radicle-cli/examples/rad-patch-merge-on-first-push.md
+++ b/crates/radicle-cli/examples/rad-patch-merge-on-first-push.md
@@ -5,15 +5,15 @@ Here we start off with Alice adding Bob as a delegate:
``` ~alice
$ rad id update --title "Add Bob" --description "Add Bob as a delegate" --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk -q
-7be665f9fccba97abb21b2fa85a6fd3181c72858
+83ac41c238b1ece55e11ca0ad8621fe5013e30e5
```
Bob clones the repository so that he can start working on it with Alice:
``` ~bob
-$ rad clone rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+$ rad clone rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -42,8 +42,8 @@ $ git commit -v -m "Define power requirements"
``` ~alice (stderr)
$ git push rad -o no-sync -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch df868fc7985fa7217aaef8423d73a077868c02b3 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch d7df6d0eb75ae67ff055f7ad61072fbe262aa248 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -52,7 +52,7 @@ first he syncs the repository:
``` ~bob
$ rad sync -f
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -60,12 +60,12 @@ Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential s
He then checks out the patch and merges the changes in:
``` ~bob
-$ rad patch checkout df868fc
-✓ Switched to branch patch/df868fc at revision df868fc
-✓ Branch patch/df868fc setup to track rad/patches/df868fc7985fa7217aaef8423d73a077868c02b3
+$ rad patch checkout d7df6d0
+✓ Switched to branch patch/d7df6d0 at revision d7df6d0
+✓ Branch patch/d7df6d0 setup to track rad/patches/d7df6d0eb75ae67ff055f7ad61072fbe262aa248
$ git checkout master
Your branch is up to date with 'rad/master'.
-$ git merge patch/df868fc
+$ git merge patch/d7df6d0
Updating f2de534..3e674d1
Fast-forward
REQUIREMENTS | 0
@@ -82,13 +82,13 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
- │ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
│ └── xyz.radicle.patch
- │ └── df868fc7985fa7217aaef8423d73a077868c02b3
+ │ └── d7df6d0eb75ae67ff055f7ad61072fbe262aa248
├── heads
│ ├── master
│ └── patches
- │ └── df868fc7985fa7217aaef8423d73a077868c02b3
+ │ └── d7df6d0eb75ae67ff055f7ad61072fbe262aa248
└── rad
├── id
├── root
@@ -101,10 +101,10 @@ Now that the changes are merged, he can push and have the patch merged:
``` ~bob (stderr)
$ git push rad master
-✓ Patch df868fc7985fa7217aaef8423d73a077868c02b3 merged
+✓ Patch d7df6d0eb75ae67ff055f7ad61072fbe262aa248 merged
✓ Canonical reference refs/heads/master updated to target commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new branch] master -> master
```
@@ -116,13 +116,13 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
└── refs
├── cobs
│ ├── xyz.radicle.id
- │ │ └── 0656c217f917c3e06234771e9ecae53aba5e173e
+ │ │ └── 86399084097fb674569f5bc5847da609ab91aa9f
│ └── xyz.radicle.patch
- │ └── df868fc7985fa7217aaef8423d73a077868c02b3
+ │ └── d7df6d0eb75ae67ff055f7ad61072fbe262aa248
├── heads
│ ├── master
│ └── patches
- │ └── df868fc7985fa7217aaef8423d73a077868c02b3
+ │ └── d7df6d0eb75ae67ff055f7ad61072fbe262aa248
└── rad
├── id
├── root
@@ -131,7 +131,7 @@ z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
└── refs
├── cobs
│ └── xyz.radicle.patch
- │ └── df868fc7985fa7217aaef8423d73a077868c02b3
+ │ └── d7df6d0eb75ae67ff055f7ad61072fbe262aa248
├── heads
│ └── master
└── rad
diff --git a/crates/radicle-cli/examples/rad-patch-merge-unauthorized-branch.md b/crates/radicle-cli/examples/rad-patch-merge-unauthorized-branch.md
index a8641accd3..69f70f296e 100644
--- a/crates/radicle-cli/examples/rad-patch-merge-unauthorized-branch.md
+++ b/crates/radicle-cli/examples/rad-patch-merge-unauthorized-branch.md
@@ -3,7 +3,7 @@
First, we update the identity document to add a canonical reference rule for a new `accepted` branch, but we only allow Alice to merge into it.
``` ~alice
-$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/accepted": { "threshold": 1, "allow": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"] } }' -q
+$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/accepted": { "threshold": 1, "allow": ["did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"] } }' -q
[..]
```
@@ -19,16 +19,16 @@ $ git commit --allow-empty -m "Initialize accepted branch"
```
``` ~alice (stderr)
$ git push rad accepted
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] accepted -> accepted
```
Next, Bob clones the repository and opens a patch targeting `accepted`.
``` ~bob
-$ rad clone rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+$ rad clone rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
✓ Remote-tracking branch alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master created for z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
@@ -57,7 +57,7 @@ $ git commit -m "Add new feature"
$ git push -o patch.message="Add new feature" -o patch.target="refs/heads/accepted" rad HEAD:refs/patches
✓ Patch [..] opened
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new reference] HEAD -> refs/patches
```
@@ -77,7 +77,7 @@ Merge made by the 'ort' strategy.
``` ~bob (stderr)
$ git push rad accepted
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new branch] accepted -> accepted
```
@@ -92,6 +92,6 @@ $ rad patch list --open
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ● [.. ] Add new feature bob (you) - [.. ] +0 -0 now │
+│ ● [..] Add new feature bob (you) - [..] +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-merge-wrong-branch.md b/crates/radicle-cli/examples/rad-patch-merge-wrong-branch.md
index 72b09f08b6..b13cfa0f52 100644
--- a/crates/radicle-cli/examples/rad-patch-merge-wrong-branch.md
+++ b/crates/radicle-cli/examples/rad-patch-merge-wrong-branch.md
@@ -3,7 +3,7 @@
First, we update the identity document to add a canonical reference rule for a new `accepted` branch.
```
-$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
+$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
[..]
```
@@ -19,8 +19,8 @@ $ git commit --allow-empty -m "Initialize accepted branch"
```
``` (stderr)
$ git push rad accepted
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] accepted -> accepted
```
@@ -41,7 +41,7 @@ $ git commit -m "Add new feature"
``` (stderr)
$ git push -o patch.message="Add new feature" -o patch.target="refs/heads/accepted" rad HEAD:refs/patches
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -62,7 +62,7 @@ Fast-forward
``` (stderr)
$ git push rad master
✓ Canonical reference refs/heads/master updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
[..]..[..] master -> master
```
@@ -77,6 +77,6 @@ $ rad patch list --open
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ● [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ● [..] Add new feature alice (you) - [..] +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-open-explore.md b/crates/radicle-cli/examples/rad-patch-open-explore.md
index 882eca5793..0d77580747 100644
--- a/crates/radicle-cli/examples/rad-patch-open-explore.md
+++ b/crates/radicle-cli/examples/rad-patch-open-explore.md
@@ -4,12 +4,12 @@ When preferred seeds are configured, opening a patch outputs the patch URL.
$ git checkout -b changes -q
$ git commit --allow-empty -q -m "Changes"
$ git push rad HEAD:refs/patches
-✓ Patch acab0ec777a97d013f30be5d5d1aec32562ecb02 opened
+✓ Patch 2b05aedac8fd1aedfe5ca2ecb6aef01a182963d4 opened
✓ Synced with 1 seed(s)
- https://radicle.network/nodes/[..]/rad:z3yXbb1sR6UG6ixxV2YF9jUP7ABra/patches/acab0ec777a97d013f30be5d5d1aec32562ecb02
+ https://radicle.network/nodes/127.0.0.1/rad:zREWtxFjVEsAkeUYBV5ZEbw3qGo8/patches/2b05aedac8fd1aedfe5ca2ecb6aef01a182963d4
-To rad://z3yXbb1sR6UG6ixxV2YF9jUP7ABra/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://zREWtxFjVEsAkeUYBV5ZEbw3qGo8/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new reference] HEAD -> refs/patches
```
@@ -18,17 +18,17 @@ If we update the patch, the URL is also output.
``` (stderr)
$ git commit --amend --allow-empty -q -m "Other changes"
$ git push -f
-✓ Patch acab0ec updated to revision f7a830d829d0cdf398f63a32b0d5ee31f08e21ab
-To compare against your previous revision acab0ec, run:
+✓ Patch 2b05aed updated to revision 5ef99963cbd182ac0cdb8db046671324a32dfcff
+To compare against your previous revision 2b05aed, run:
- git range-diff f2de534[..] e12525d[..] b2b6432[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 e12525d99b1415b9bccf4ed87050ab25eb86e2c4 b2b6432af93f8fe188e32d400263021b602cfec8
✓ Synced with 1 seed(s)
- https://radicle.network/nodes/[..]/rad:z3yXbb1sR6UG6ixxV2YF9jUP7ABra/patches/acab0ec777a97d013f30be5d5d1aec32562ecb02
+ https://radicle.network/nodes/127.0.0.1/rad:zREWtxFjVEsAkeUYBV5ZEbw3qGo8/patches/2b05aedac8fd1aedfe5ca2ecb6aef01a182963d4
-To rad://z3yXbb1sR6UG6ixxV2YF9jUP7ABra/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
- + e12525d...b2b6432 changes -> patches/acab0ec777a97d013f30be5d5d1aec32562ecb02 (forced update)
+To rad://zREWtxFjVEsAkeUYBV5ZEbw3qGo8/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+ + e12525d...b2b6432 changes -> patches/2b05aedac8fd1aedfe5ca2ecb6aef01a182963d4 (forced update)
```
While simply pushing a commit outputs a URL to the new source tree.
@@ -37,12 +37,12 @@ While simply pushing a commit outputs a URL to the new source tree.
$ git checkout master -q
$ git merge changes -q
$ git push rad master
-✓ Patch acab0ec777a97d013f30be5d5d1aec32562ecb02 merged
+✓ Patch 2b05aedac8fd1aedfe5ca2ecb6aef01a182963d4 merged
✓ Canonical reference refs/heads/master updated to target commit b2b6432af93f8fe188e32d400263021b602cfec8
✓ Synced with 1 seed(s)
- https://radicle.network/nodes/[..]/rad:z3yXbb1sR6UG6ixxV2YF9jUP7ABra/tree/b2b6432af93f8fe188e32d400263021b602cfec8
+ https://radicle.network/nodes/127.0.0.1/rad:zREWtxFjVEsAkeUYBV5ZEbw3qGo8/tree/b2b6432af93f8fe188e32d400263021b602cfec8
-To rad://z3yXbb1sR6UG6ixxV2YF9jUP7ABra/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://zREWtxFjVEsAkeUYBV5ZEbw3qGo8/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
f2de534..b2b6432 master -> master
```
diff --git a/crates/radicle-cli/examples/rad-patch-pull-update.md b/crates/radicle-cli/examples/rad-patch-pull-update.md
index 44aca4c29e..bbd4b081ae 100644
--- a/crates/radicle-cli/examples/rad-patch-pull-update.md
+++ b/crates/radicle-cli/examples/rad-patch-pull-update.md
@@ -9,7 +9,7 @@ Initializing public Radicle 👾 repository in [..]
✓ Repository heartwood created.
-Your Repository ID (RID) is rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
+Your Repository ID (RID) is rad:z41A7PnmXror3L2oP1vq81vhCQPBc
You can show it any time by running `rad .` from this directory.
✓ Repository successfully announced to the network.
@@ -21,9 +21,9 @@ To push changes, run `git push`.
```
``` ~bob
-$ rad clone rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK
-✓ Seeding policy updated for rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK with scope 'followed'
-Fetching rad:zhbMU4DUXrzB8xT6qAJh6yZ7bFMK from the network, found 1 potential seed(s).
+$ rad clone rad:z41A7PnmXror3L2oP1vq81vhCQPBc
+✓ Seeding policy updated for rad:z41A7PnmXror3L2oP1vq81vhCQPBc with scope 'followed'
+Fetching rad:z41A7PnmXror3L2oP1vq81vhCQPBc from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Creating checkout in ./heartwood..
✓ Remote alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi added
@@ -44,7 +44,7 @@ our fork:
$ cd heartwood
$ git push rad master
✓ Synced with 1 seed(s)
-To rad://zhbMU4DUXrzB8xT6qAJh6yZ7bFMK/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z41A7PnmXror3L2oP1vq81vhCQPBc/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new branch] master -> master
```
@@ -54,22 +54,22 @@ Bob then opens a patch.
$ git checkout -b bob/feature -q
$ git commit --allow-empty -m "Bob's commit #1" -q
$ git push rad -o sync -o patch.message="Bob's patch" HEAD:refs/patches
-✓ Patch 55b9721ed7f6bfec38f43729e9b6631c5dc812fb opened
+✓ Patch 9a01007e4b6dfed6dfc14a207b483e856624f61e opened
✓ Synced with 1 seed(s)
-To rad://zhbMU4DUXrzB8xT6qAJh6yZ7bFMK/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+To rad://z41A7PnmXror3L2oP1vq81vhCQPBc/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new reference] HEAD -> refs/patches
```
``` ~bob
$ git status --short --branch
-## bob/feature...rad/patches/55b9721ed7f6bfec38f43729e9b6631c5dc812fb
+## bob/feature...rad/patches/9a01007e4b6dfed6dfc14a207b483e856624f61e
```
Alice checks it out.
``` ~alice
-$ rad patch checkout 55b9721ed7f6bfec38f43729e9b6631c5dc812fb
-✓ Switched to branch patch/55b9721 at revision 55b9721
-✓ Branch patch/55b9721 setup to track rad/patches/55b9721ed7f6bfec38f43729e9b6631c5dc812fb
+$ rad patch checkout 9a01007e4b6dfed6dfc14a207b483e856624f61e
+✓ Switched to branch patch/9a01007 at revision 9a01007
+✓ Branch patch/9a01007 setup to track rad/patches/9a01007e4b6dfed6dfc14a207b483e856624f61e
$ git show
commit bdcdb30b3c0f513620dd0f1c24ff8f4f71de956b
Author: radicle <radicle@localhost>
@@ -83,26 +83,26 @@ Bob then updates the patch.
``` ~bob (stderr)
$ git commit --allow-empty -m "Bob's commit #2" -q
$ git push rad -o sync -o patch.message="Updated."
-✓ Patch 55b9721 updated to revision f91e056da05b2d9a58af1160c76245bc3debf7a8
-To compare against your previous revision 55b9721, run:
+✓ Patch 9a01007 updated to revision 90c8597aeaa247290d42665d01c363bfe67d1818
+To compare against your previous revision 9a01007, run:
- git range-diff f2de534[..] bdcdb30[..] cad2666[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 bdcdb30b3c0f513620dd0f1c24ff8f4f71de956b cad2666a8a2250e4dee175ed5044be2c251ff08b
✓ Synced with 1 seed(s)
-To rad://zhbMU4DUXrzB8xT6qAJh6yZ7bFMK/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
- bdcdb30..cad2666 bob/feature -> patches/55b9721ed7f6bfec38f43729e9b6631c5dc812fb
+To rad://z41A7PnmXror3L2oP1vq81vhCQPBc/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+ bdcdb30..cad2666 bob/feature -> patches/9a01007e4b6dfed6dfc14a207b483e856624f61e
```
Alice pulls the update.
``` ~alice
-$ rad patch show 55b9721
+$ rad patch show 9a01007
╭──────────────────────────────────────────────────────────────────╮
│ Title Bob's patch │
-│ Patch 55b9721ed7f6bfec38f43729e9b6631c5dc812fb │
+│ Patch 9a01007e4b6dfed6dfc14a207b483e856624f61e │
│ Author bob z6Mkt67…v4N1tRk │
│ Head cad2666a8a2250e4dee175ed5044be2c251ff08b │
-│ Base [.. ] │
+│ Base f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 │
│ Target master │
│ Commits ahead 2, behind 0 │
│ Status open │
@@ -110,18 +110,18 @@ $ rad patch show 55b9721
│ cad2666 Bob's commit #2 │
│ bdcdb30 Bob's commit #1 │
├──────────────────────────────────────────────────────────────────┤
-│ ● Revision 55b9721 @ [.. ]..bdcdb30 by bob z6Mkt67…v4N1tRk now │
-│ ↑ Revision f91e056 @ [.. ]..cad2666 by bob z6Mkt67…v4N1tRk now │
+│ ● Revision 9a01007 @ f2de534..bdcdb30 by bob z6Mkt67…v4N1tRk now │
+│ ↑ Revision 90c8597 @ f2de534..cad2666 by bob z6Mkt67…v4N1tRk now │
╰──────────────────────────────────────────────────────────────────╯
$ git ls-remote rad
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
-cad2666a8a2250e4dee175ed5044be2c251ff08b refs/heads/patches/55b9721ed7f6bfec38f43729e9b6631c5dc812fb
+cad2666a8a2250e4dee175ed5044be2c251ff08b refs/heads/patches/9a01007e4b6dfed6dfc14a207b483e856624f61e
```
``` ~alice
$ git fetch rad
$ git status --short --branch
-## patch/55b9721...rad/patches/55b9721ed7f6bfec38f43729e9b6631c5dc812fb [behind 1]
+## patch/9a01007...rad/patches/9a01007e4b6dfed6dfc14a207b483e856624f61e [behind 1]
```
``` ~alice
$ git pull
diff --git a/crates/radicle-cli/examples/rad-patch-revert-custom-branch.md b/crates/radicle-cli/examples/rad-patch-revert-custom-branch.md
index 63cf5ce994..1161a2cb44 100644
--- a/crates/radicle-cli/examples/rad-patch-revert-custom-branch.md
+++ b/crates/radicle-cli/examples/rad-patch-revert-custom-branch.md
@@ -3,7 +3,7 @@
First, we update the identity document to add a canonical reference rule for a new `accepted` branch.
```
-$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
+$ rad id update --title "Add accepted branch" --payload xyz.radicle.crefs rules '{ "refs/heads/master": { "threshold": 1, "allow": "delegates" }, "refs/heads/accepted": { "threshold": 1, "allow": "delegates" } }' -q
[..]
```
@@ -19,8 +19,8 @@ $ git commit --allow-empty -m "Initialize accepted branch"
```
``` (stderr)
$ git push rad accepted
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new branch] accepted -> accepted
```
@@ -41,7 +41,7 @@ $ git commit -m "Add new feature"
``` (stderr)
$ git push -o patch.message="Add new feature" -o patch.target="refs/heads/accepted" rad HEAD:refs/patches
✓ Patch [..] opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -61,10 +61,10 @@ Fast-forward
```
``` (stderr)
$ git push rad accepted
-✓ Patch [..] merged
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- [..]..[..] accepted -> accepted
+✓ Patch 38592f91ee06aeb38c88a5352ca4254accff3591 merged
+✓ Canonical reference refs/heads/accepted updated to target commit 27acd3b208662f374b34cd4c599f3628c9e42b80
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f9a3b89..27acd3b accepted -> accepted
```
We verify the patch is merged.
@@ -74,7 +74,7 @@ $ rad patch list --merged
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ✓ [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ✓ 38592f9 Add new feature alice (you) - 27acd3b +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -94,7 +94,7 @@ HEAD is now at [..] Initial commit
``` (stderr)
$ git push rad master --force
✓ Canonical reference refs/heads/master updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ f2de534...08c788d master -> master (forced update)
```
@@ -106,7 +106,7 @@ $ rad patch list --merged
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ✓ [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ✓ 38592f9 Add new feature alice (you) - 27acd3b +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -124,9 +124,9 @@ HEAD is now at [..] Initialize accepted branch
```
``` (stderr)
$ git push rad accepted --force
-! Patch [..] reverted at revision [..]
-✓ Canonical reference refs/heads/accepted updated to target commit [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+! Patch 38592f91ee06aeb38c88a5352ca4254accff3591 reverted at revision 38592f9
+✓ Canonical reference refs/heads/accepted updated to target commit f9a3b8998a3922a1e542a3dc93299c82649da455
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 27acd3b...f9a3b89 accepted -> accepted (forced update)
```
@@ -141,6 +141,6 @@ $ rad patch list --open
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ● [.. ] Add new feature alice (you) - [.. ] +0 -0 now │
+│ ● [..] Add new feature alice (you) - [..] +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-revert-merge.md b/crates/radicle-cli/examples/rad-patch-revert-merge.md
index a0c58d070e..eb4c6e49fd 100644
--- a/crates/radicle-cli/examples/rad-patch-revert-merge.md
+++ b/crates/radicle-cli/examples/rad-patch-revert-merge.md
@@ -4,29 +4,29 @@ Let's create a patch, merge it and then revert it.
$ git checkout -b feature/1 -q
$ git commit --allow-empty -q -m "First change"
$ git push rad HEAD:refs/patches
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
$ git checkout master
Switched to branch 'master'
$ git merge feature/1
$ git push rad master
-✓ Patch 696ec5508494692899337afe6713fe1796d0315c merged
+✓ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 merged
✓ Canonical reference refs/heads/master updated to target commit 20aa5dde6210796c3a2f04079b42316a31d02689
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..20aa5dd master -> master
```
First we see the patch as merged.
```
-$ rad patch show 696ec5508494692899337afe6713fe1796d0315c
+$ rad patch show 43362c8b437a0ce6798a762f3676e4dd68b67792
╭──────────────────────────────────────────────────────────╮
│ Title First change │
-│ Patch 696ec5508494692899337afe6713fe1796d0315c │
+│ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 │
│ Author alice (you) │
│ Head 20aa5dde6210796c3a2f04079b42316a31d02689 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1, master │
│ Commits up to date │
@@ -34,7 +34,7 @@ $ rad patch show 696ec5508494692899337afe6713fe1796d0315c
├──────────────────────────────────────────────────────────┤
│ 20aa5dd First change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 696ec55 @ [.. ]..20aa5dd by alice (you) now │
+│ ● Revision 43362c8 @ [..]..20aa5dd by alice (you) now │
│ └─ ✓ merged by alice (you) │
╰──────────────────────────────────────────────────────────╯
```
@@ -51,22 +51,22 @@ When pushing, notice that we're told our patch is reverted.
``` (stderr) RAD_SOCKET=/dev/null
$ git push rad master --force
-! Patch 696ec5508494692899337afe6713fe1796d0315c reverted at revision 696ec55
+! Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 reverted at revision 43362c8
✓ Canonical reference refs/heads/master updated to target commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 20aa5dd...f2de534 master -> master (forced update)
```
The patch shows up as open again.
```
-$ rad patch show 696ec5508494692899337afe6713fe1796d0315c
+$ rad patch show 43362c8b437a0ce6798a762f3676e4dd68b67792
╭──────────────────────────────────────────────────────────╮
│ Title First change │
-│ Patch 696ec5508494692899337afe6713fe1796d0315c │
+│ Patch 43362c8b437a0ce6798a762f3676e4dd68b67792 │
│ Author alice (you) │
│ Head 20aa5dde6210796c3a2f04079b42316a31d02689 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1 │
│ Commits ahead 1, behind 0 │
@@ -74,6 +74,6 @@ $ rad patch show 696ec5508494692899337afe6713fe1796d0315c
├──────────────────────────────────────────────────────────┤
│ 20aa5dd First change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 696ec55 @ [.. ]..20aa5dd by alice (you) now │
+│ ● Revision 43362c8 @ [..]..20aa5dd by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-review-no-options.md b/crates/radicle-cli/examples/rad-patch-review-no-options.md
index 4853ec64cf..7d399644d1 100644
--- a/crates/radicle-cli/examples/rad-patch-review-no-options.md
+++ b/crates/radicle-cli/examples/rad-patch-review-no-options.md
@@ -2,15 +2,15 @@ The `rad patch review` command must provide an option or a review message, since
a review must have a verdict or a review summary:
``` (fail)
-$ rad patch review aa45913 --no-message --no-announce
+$ rad patch review 26ba061 --no-message --no-announce
✗ Error: expected one of `--accept` or `--reject`, or supply a review message
```
This time we will supply a message:
```
-$ rad patch review aa45913 -m "Looks reasonable, no strong opinion." --no-announce
-✓ Patch aa45913 reviewed
+$ rad patch review 26ba061 -m "Looks reasonable, no strong opinion." --no-announce
+✓ Patch 26ba061 reviewed
```
Submitting a second review on the same revision by the same author is ignored.
@@ -19,6 +19,6 @@ Currently, there is no way to edit a review from the CLI.
Note that the review command will still succeed, but with no effect:
```
-$ rad patch review aa45913 -m "Changed my mind." --no-announce
-✓ Patch aa45913 reviewed
+$ rad patch review 26ba061 -m "Changed my mind." --no-announce
+✓ Patch 26ba061 reviewed
```
diff --git a/crates/radicle-cli/examples/rad-patch-update.md b/crates/radicle-cli/examples/rad-patch-update.md
index 67934e0ba7..f5b2f84b7f 100644
--- a/crates/radicle-cli/examples/rad-patch-update.md
+++ b/crates/radicle-cli/examples/rad-patch-update.md
@@ -6,19 +6,19 @@ $ git commit -q -m "Not a real change" --allow-empty
```
``` (stderr)
$ git push rad HEAD:refs/patches
-✓ Patch b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch faba3f83f5497caa87ba98be85205b30c5e3afa7 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
```
-$ rad patch show b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5
+$ rad patch show faba3f83f5497caa87ba98be85205b30c5e3afa7
╭──────────────────────────────────────────────────────────╮
│ Title Not a real change │
-│ Patch b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5 │
+│ Patch faba3f83f5497caa87ba98be85205b30c5e3afa7 │
│ Author alice (you) │
│ Head 51b2f0f77b9849bfaa3e9d3ff68ee2f57771d20c │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1 │
│ Commits ahead 1, behind 0 │
@@ -26,7 +26,7 @@ $ rad patch show b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5
├──────────────────────────────────────────────────────────┤
│ 51b2f0f Not a real change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision b6a23eb @ [.. ]..51b2f0f by alice (you) now │
+│ ● Revision faba3f8 @ [..]..51b2f0f by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -48,20 +48,20 @@ Now, instead of using `git push` to update the patch, as we normally would,
we run:
```
-$ rad patch update b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5 -m "Updated patch" --no-announce
-ea7def3857f62f404606d7cd6490cd0de4eaebd1
+$ rad patch update faba3f83f5497caa87ba98be85205b30c5e3afa7 -m "Updated patch" --no-announce
+078d917942c7a39c525686b9164fa27b544df5a1
```
The command outputs the new Revision ID, which we can now see here:
```
-$ rad patch show b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5
+$ rad patch show faba3f83f5497caa87ba98be85205b30c5e3afa7
╭──────────────────────────────────────────────────────────╮
│ Title Not a real change │
-│ Patch b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5 │
+│ Patch faba3f83f5497caa87ba98be85205b30c5e3afa7 │
│ Author alice (you) │
│ Head 4d272148458a17620541555b1f0905c01658aa9f │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1 │
│ Commits ahead 2, behind 0 │
@@ -70,7 +70,7 @@ $ rad patch show b6a23eb08656de0ef1fcc0b5fe8820841e5cb2e5
│ 4d27214 Rename readme file │
│ 51b2f0f Not a real change │
├──────────────────────────────────────────────────────────┤
-│ ● Revision b6a23eb @ [.. ]..51b2f0f by alice (you) now │
-│ ↑ Revision ea7def3 @ [.. ]..4d27214 by alice (you) now │
+│ ● Revision faba3f8 @ [..]..51b2f0f by alice (you) now │
+│ ↑ Revision 078d917 @ f2de534..4d27214 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-patch-via-push.md b/crates/radicle-cli/examples/rad-patch-via-push.md
index 7d99aac65e..05efb0a5ac 100644
--- a/crates/radicle-cli/examples/rad-patch-via-push.md
+++ b/crates/radicle-cli/examples/rad-patch-via-push.md
@@ -8,24 +8,24 @@ $ git checkout -b feature/1
Switched to a new branch 'feature/1'
$ git commit -a -m "Add things" -q --allow-empty
$ git push -o patch.message="Add things #1" -o patch.message="See commits for details." rad HEAD:refs/patches
-✓ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 opened
-hint: to update, run `git push` or `git push rad --force-with-lease HEAD:patches/6035d2f582afbe01ff23ea87528ae523d76875b6`
+✓ Patch 4e0b866a7ac15131ad472888528ae0e048ee952f opened
+hint: to update, run `git push` or `git push rad --force-with-lease HEAD:patches/4e0b866a7ac15131ad472888528ae0e048ee952f`
hint: offline push, your node is not running
hint: to sync with the network, run `rad node start`
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
We can see a patch was created:
```
-$ rad patch show 6035d2f582afbe01ff23ea87528ae523d76875b6
+$ rad patch show 4e0b866a7ac15131ad472888528ae0e048ee952f
╭──────────────────────────────────────────────────────────╮
│ Title Add things #1 │
-│ Patch 6035d2f582afbe01ff23ea87528ae523d76875b6 │
+│ Patch 4e0b866a7ac15131ad472888528ae0e048ee952f │
│ Author alice (you) │
│ Head 42d894a83c9c356552a57af09ccdbd5587a99045 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/1 │
│ Commits ahead 1, behind 0 │
@@ -35,7 +35,7 @@ $ rad patch show 6035d2f582afbe01ff23ea87528ae523d76875b6
├──────────────────────────────────────────────────────────┤
│ 42d894a Add things │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 6035d2f @ [.. ]..42d894a by alice (you) now │
+│ ● Revision 4e0b866 @ f2de534..42d894a by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -44,7 +44,7 @@ branch associated with this patch:
```
$ git branch -vv
-* feature/1 42d894a [rad/patches/6035d2f582afbe01ff23ea87528ae523d76875b6] Add things
+* feature/1 42d894a [rad/patches/4e0b866a7ac15131ad472888528ae0e048ee952f] Add things
master f2de534 [rad/master] Second commit
```
@@ -52,7 +52,7 @@ Let's check that it's up to date with our local head:
```
$ git status --short --branch
-## feature/1...rad/patches/6035d2f582afbe01ff23ea87528ae523d76875b6
+## feature/1...rad/patches/4e0b866a7ac15131ad472888528ae0e048ee952f
$ git fetch
$ git push
```
@@ -64,14 +64,14 @@ $ git show-ref
42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/feature/1
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/heads/master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 refs/remotes/rad/master
-42d894a83c9c356552a57af09ccdbd5587a99045 refs/remotes/rad/patches/6035d2f582afbe01ff23ea87528ae523d76875b6
+42d894a83c9c356552a57af09ccdbd5587a99045 refs/remotes/rad/patches/4e0b866a7ac15131ad472888528ae0e048ee952f
```
```
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji 'refs/heads/patches/*'
-42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/patches/6035d2f582afbe01ff23ea87528ae523d76875b6
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/cobs/*'
-0656c217f917c3e06234771e9ecae53aba5e173e refs/cobs/xyz.radicle.id/0656c217f917c3e06234771e9ecae53aba5e173e
-6035d2f582afbe01ff23ea87528ae523d76875b6 refs/cobs/xyz.radicle.patch/6035d2f582afbe01ff23ea87528ae523d76875b6
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G 'refs/heads/patches/*'
+42d894a83c9c356552a57af09ccdbd5587a99045 refs/heads/patches/4e0b866a7ac15131ad472888528ae0e048ee952f
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi 'refs/cobs/*'
+86399084097fb674569f5bc5847da609ab91aa9f refs/cobs/xyz.radicle.id/86399084097fb674569f5bc5847da609ab91aa9f
+4e0b866a7ac15131ad472888528ae0e048ee952f refs/cobs/xyz.radicle.patch/4e0b866a7ac15131ad472888528ae0e048ee952f
```
We can create another patch:
@@ -80,8 +80,8 @@ We can create another patch:
$ git checkout -b feature/2 -q master
$ git commit -a -m "Add more things" -q --allow-empty
$ git push rad HEAD:refs/patches
-✓ Patch 95808913573cead52ad7b42c7b475260ec45c4b2 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 368960ee1cd815c40c68cc776cbe6bd4db48b287 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -89,8 +89,8 @@ We see both branches with upstreams now:
```
$ git branch -vv
- feature/1 42d894a [rad/patches/6035d2f582afbe01ff23ea87528ae523d76875b6] Add things
-* feature/2 8b0ea80 [rad/patches/95808913573cead52ad7b42c7b475260ec45c4b2] Add more things
+ feature/1 42d894a [rad/patches/4e0b866a7ac15131ad472888528ae0e048ee952f] Add things
+* feature/2 8b0ea80 [rad/patches/368960ee1cd815c40c68cc776cbe6bd4db48b287] Add more things
master f2de534 [rad/master] Second commit
```
@@ -101,8 +101,8 @@ $ rad patch
╭───────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├───────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 6035d2f Add things #1 alice (you) - 42d894a +0 -0 now │
-│ ● 9580891 Add more things alice (you) - 8b0ea80 +0 -0 now │
+│ ● 368960e Add more things alice (you) - 8b0ea80 +0 -0 now │
+│ ● 4e0b866 Add things #1 alice (you) - 42d894a +0 -0 now │
╰───────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -114,13 +114,13 @@ $ git commit -a -m "Improve code" -q --allow-empty
``` (stderr)
$ git push rad
-✓ Patch 9580891 updated to revision d7040c6c97629c2b94f86fb639bebbff5de39697
-To compare against your previous revision 9580891, run:
+✓ Patch 368960e updated to revision f951ceca85e932c74eaa8d8cba16ce4712835f03
+To compare against your previous revision 368960e, run:
- git range-diff f2de534[..] 8b0ea80[..] 02bef3f[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 8b0ea80d3acd2c55e8820b3064e7575934158b4d 02bef3fac41b2f98bb3c02b868a53ddfecb55b5f
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 8b0ea80..02bef3f feature/2 -> patches/95808913573cead52ad7b42c7b475260ec45c4b2
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 8b0ea80..02bef3f feature/2 -> patches/368960ee1cd815c40c68cc776cbe6bd4db48b287
```
This last `git push` worked without specifying an upstream branch despite the
@@ -138,13 +138,13 @@ This allows for pushing to the remote patch branch without using the full
We can then see that the patch head has moved:
```
-$ rad patch show 9580891
+$ rad patch show 368960e
╭──────────────────────────────────────────────────────────╮
│ Title Add more things │
-│ Patch 95808913573cead52ad7b42c7b475260ec45c4b2 │
+│ Patch 368960ee1cd815c40c68cc776cbe6bd4db48b287 │
│ Author alice (you) │
│ Head 02bef3fac41b2f98bb3c02b868a53ddfecb55b5f │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/2 │
│ Commits ahead 2, behind 0 │
@@ -153,8 +153,8 @@ $ rad patch show 9580891
│ 02bef3f Improve code │
│ 8b0ea80 Add more things │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 9580891 @ [.. ]..8b0ea80 by alice (you) now │
-│ ↑ Revision d7040c6 @ [.. ]..02bef3f by alice (you) now │
+│ ● Revision 368960e @ [..]..8b0ea80 by alice (you) now │
+│ ↑ Revision f951cec @ [..]..02bef3f by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -167,14 +167,14 @@ $ git rev-parse HEAD
```
$ git status --short --branch
-## feature/2...rad/patches/95808913573cead52ad7b42c7b475260ec45c4b2
+## feature/2...rad/patches/368960ee1cd815c40c68cc776cbe6bd4db48b287
```
```
-$ git rev-parse refs/remotes/rad/patches/95808913573cead52ad7b42c7b475260ec45c4b2
+$ git rev-parse refs/remotes/rad/patches/368960ee1cd815c40c68cc776cbe6bd4db48b287
02bef3fac41b2f98bb3c02b868a53ddfecb55b5f
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/patches/95808913573cead52ad7b42c7b475260ec45c4b2
-02bef3fac41b2f98bb3c02b868a53ddfecb55b5f refs/heads/patches/95808913573cead52ad7b42c7b475260ec45c4b2
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi refs/heads/patches/368960ee1cd815c40c68cc776cbe6bd4db48b287
+02bef3fac41b2f98bb3c02b868a53ddfecb55b5f refs/heads/patches/368960ee1cd815c40c68cc776cbe6bd4db48b287
```
## Force push
@@ -194,9 +194,9 @@ Now let's push to the patch head.
``` (stderr) (fail)
$ git push
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- ! [rejected] feature/2 -> patches/95808913573cead52ad7b42c7b475260ec45c4b2 (non-fast-forward)
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ ! [rejected] feature/2 -> patches/368960ee1cd815c40c68cc776cbe6bd4db48b287 (non-fast-forward)
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
hint: [..]
hint: [..]
hint: [..]
@@ -208,25 +208,25 @@ use `--force-with-lease` (or `--force`) to force the update.
``` (stderr)
$ git push --force-with-lease
-✓ Patch 9580891 updated to revision 670d02794aa05afd6e0851f4aa848bc87c4712c7
-To compare against your previous revision d7040c6, run:
+✓ Patch 368960e updated to revision af867d0de56c5d8d000c390e580f180d5c20ad63
+To compare against your previous revision f951cec, run:
- git range-diff f2de534[..] 02bef3f[..] 9304dbc[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 02bef3fac41b2f98bb3c02b868a53ddfecb55b5f 9304dbc445925187994a7a93222a3f8bde73b785
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- + 02bef3f...9304dbc feature/2 -> patches/95808913573cead52ad7b42c7b475260ec45c4b2 (forced update)
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ + 02bef3f...9304dbc feature/2 -> patches/368960ee1cd815c40c68cc776cbe6bd4db48b287 (forced update)
```
That worked. We can see the new revision if we call `rad patch show`:
```
-$ rad patch show 9580891
+$ rad patch show 368960e
╭──────────────────────────────────────────────────────────╮
│ Title Add more things │
-│ Patch 95808913573cead52ad7b42c7b475260ec45c4b2 │
+│ Patch 368960ee1cd815c40c68cc776cbe6bd4db48b287 │
│ Author alice (you) │
│ Head 9304dbc445925187994a7a93222a3f8bde73b785 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches feature/2 │
│ Commits ahead 2, behind 0 │
@@ -235,9 +235,9 @@ $ rad patch show 9580891
│ 9304dbc Amended commit │
│ 8b0ea80 Add more things │
├──────────────────────────────────────────────────────────┤
-│ ● Revision 9580891 @ [.. ]..8b0ea80 by alice (you) now │
-│ ↑ Revision d7040c6 @ [.. ]..02bef3f by alice (you) now │
-│ ↑ Revision 670d027 @ [.. ]..9304dbc by alice (you) now │
+│ ● Revision 368960e @ [..]..8b0ea80 by alice (you) now │
+│ ↑ Revision f951cec @ [..]..02bef3f by alice (you) now │
+│ ↑ Revision af867d0 @ [..]..9304dbc by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -273,10 +273,10 @@ Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 831e838 Going into detached HEAD
$ git push rad HEAD:refs/patches -o patch.branch
-✓ Patch e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 opened
-✓ Branch patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 created
-hint: to update, run `git push rad patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3`
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 93f89aa5ff91975938077ac27dfe0509e63ae45b opened
+✓ Branch patches/93f89aa5ff91975938077ac27dfe0509e63ae45b created
+hint: to update, run `git push rad patches/93f89aa5ff91975938077ac27dfe0509e63ae45b`
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -284,17 +284,17 @@ The default name used for the branch is `patches/<patch id>`. So let's checkout
the branch and push a new revision:
``` (stderr)
-$ git checkout patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
-Switched to branch 'patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3'
+$ git checkout patches/93f89aa5ff91975938077ac27dfe0509e63ae45b
+Switched to branch 'patches/93f89aa5ff91975938077ac27dfe0509e63ae45b'
$ git commit --allow-empty -m "Pushing new revision"
$ git push rad
-✓ Patch e0fd879 updated to revision 943cbd9769e855d5e4eba419e68374c5141a2785
-To compare against your previous revision e0fd879, run:
+✓ Patch 93f89aa updated to revision c55e519073994d2904fab46988c8b2bca703624a
+To compare against your previous revision 93f89aa, run:
git range-diff [..] [..] [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 831e838..d0ff2a1 patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 -> patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 831e838..d0ff2a1 patches/93f89aa5ff91975938077ac27dfe0509e63ae45b -> patches/93f89aa5ff91975938077ac27dfe0509e63ae45b
```
However, we also allow you to name the branch yourself:
@@ -302,10 +302,10 @@ However, we also allow you to name the branch yourself:
``` (stderr)
$ git checkout 831e838 -q
$ git push rad HEAD:refs/patches -o patch.branch='feature/3'
-✓ Patch e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3 opened
+✓ Patch 93f89aa5ff91975938077ac27dfe0509e63ae45b opened
✓ Branch feature/3 created
hint: to update, run `git push rad feature/3`
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -316,13 +316,13 @@ $ git checkout feature/3
Switched to branch 'feature/3'
$ git commit --allow-empty -m "Pushing new revision"
$ git push rad
-✓ Patch e0fd879 updated to revision 943cbd9769e855d5e4eba419e68374c5141a2785
-To compare against your previous revision e0fd879, run:
+✓ Patch 93f89aa updated to revision c55e519073994d2904fab46988c8b2bca703624a
+To compare against your previous revision 93f89aa, run:
git range-diff [..] [..] [..]
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 831e838..d0ff2a1 feature/3 -> patches/e0fd879ac0a7d3ddcf3b440d8db656f5d7cebea3
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 831e838..d0ff2a1 feature/3 -> patches/93f89aa5ff91975938077ac27dfe0509e63ae45b
```
## Empty patch
@@ -333,7 +333,7 @@ we should get an error:
``` (stderr) (fail)
$ git push rad master:refs/patches
warn: attempted to create a patch using the commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354, but this commit is already included in the base branch
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
! [remote rejected] master -> refs/patches (patch commits are already included in the base branch)
-error: failed to push some refs to 'rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
+error: failed to push some refs to 'rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi'
```
diff --git a/crates/radicle-cli/examples/rad-patch.md b/crates/radicle-cli/examples/rad-patch.md
index 875d7b39e4..e9a8558960 100644
--- a/crates/radicle-cli/examples/rad-patch.md
+++ b/crates/radicle-cli/examples/rad-patch.md
@@ -26,8 +26,8 @@ Once the code is ready, we open (or create) a patch with our changes for the pro
``` (stderr)
$ git push rad -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch aa45913e757cacd46972733bddee5472c78fa32a opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -38,17 +38,17 @@ $ rad patch
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● aa45913 Define power requirements alice (you) - 3e674d1 +0 -0 now │
+│ ● 26ba061 Define power requirements alice (you) - 3e674d1 +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
```
```
-$ rad patch show aa45913e757cacd46972733bddee5472c78fa32a -p
+$ rad patch show 26ba0615c6e911344ee61d53241a2903c5bf8623 -p
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch aa45913e757cacd46972733bddee5472c78fa32a │
+│ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 │
│ Author alice (you) │
│ Head 3e674d1a1df90807e934f9ae5da2591dd6848a33 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches flux-capacitor-power │
│ Commits ahead 1, behind 0 │
@@ -58,7 +58,7 @@ $ rad patch show aa45913e757cacd46972733bddee5472c78fa32a -p
├──────────────────────────────────────────────────────────┤
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision aa45913 @ [.. ]..3e674d1 by alice (you) now │
+│ ● Revision 26ba061 @ [..]..3e674d1 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
commit 3e674d1a1df90807e934f9ae5da2591dd6848a33
@@ -80,14 +80,14 @@ $ rad patch list --authored
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● aa45913 Define power requirements alice (you) - 3e674d1 +0 -0 now │
+│ ● 26ba061 Define power requirements alice (you) - 3e674d1 +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
```
We can also see that it set an upstream for our patch branch:
```
$ git branch -vv
-* flux-capacitor-power 3e674d1 [rad/patches/aa45913e757cacd46972733bddee5472c78fa32a] Define power requirements
+* flux-capacitor-power 3e674d1 [rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623] Define power requirements
master f2de534 [rad/master] Second commit
```
@@ -95,16 +95,16 @@ We can also label patches as well as assign DIDs to the patch to help
organise your workflow:
```
-$ rad patch label aa45913 --add fun --no-announce
-$ rad patch assign aa45913 --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
-$ rad patch show aa45913
+$ rad patch label 26ba061 --add fun --no-announce
+$ rad patch assign 26ba061 --add did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --no-announce
+$ rad patch show 26ba061
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch aa45913e757cacd46972733bddee5472c78fa32a │
+│ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 │
│ Author alice (you) │
│ Labels fun │
│ Head 3e674d1a1df90807e934f9ae5da2591dd6848a33 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches flux-capacitor-power │
│ Commits ahead 1, behind 0 │
@@ -114,7 +114,7 @@ $ rad patch show aa45913
├──────────────────────────────────────────────────────────┤
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision aa45913 @ [.. ]..3e674d1 by alice (you) now │
+│ ● Revision 26ba061 @ [..]..3e674d1 by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
@@ -130,33 +130,33 @@ $ git commit --message "Add README, just for the fun"
```
``` (stderr)
$ git push rad -o patch.message="Add README, just for the fun"
-✓ Patch aa45913 updated to revision 6e5a3b7b2ce27b32e7ccc2f0b3f4594897dde638
-To compare against your previous revision aa45913, run:
+✓ Patch 26ba061 updated to revision d0013e385c76a82e5f62df467e735fd96bd69a00
+To compare against your previous revision 26ba061, run:
- git range-diff f2de534[..] 3e674d1[..] 27857ec[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 3e674d1a1df90807e934f9ae5da2591dd6848a33 27857ec9eb04c69cacab516e8bf4b5fd36090f66
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- 3e674d1..27857ec flux-capacitor-power -> patches/aa45913e757cacd46972733bddee5472c78fa32a
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ 3e674d1..27857ec flux-capacitor-power -> patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
And let's leave a quick comment for our team:
```
-$ rad patch comment aa45913 --message 'I cannot wait to get back to the 90s!' --no-announce
+$ rad patch comment 26ba061 --message 'I cannot wait to get back to the 90s!' --no-announce
╭───────────────────────────────────────╮
-│ alice (you) now 686ec1c │
+│ alice (you) now 30c6a91 │
│ I cannot wait to get back to the 90s! │
╰───────────────────────────────────────╯
-$ rad patch comment aa45913 --message 'My favorite decade!' --reply-to 686ec1c -q --no-announce
-f4336e42daf76342f787d574b5ee779d89d05c7a
+$ rad patch comment 26ba061 --message 'My favorite decade!' --reply-to 30c6a91 -q --no-announce
+e99153259a09f5a15e385e531a5943d314245db1
```
If we realize we made a mistake in the comment, we can go back and edit it:
```
-$ rad patch comment aa45913 --edit 686ec1c --message 'I cannot wait to get back to the 80s!' --no-announce
+$ rad patch comment 26ba061 --edit 30c6a91 --message 'I cannot wait to get back to the 80s!' --no-announce
╭───────────────────────────────────────╮
-│ alice (you) now 686ec1c │
+│ alice (you) now 30c6a91 │
│ I cannot wait to get back to the 80s! │
╰───────────────────────────────────────╯
```
@@ -164,38 +164,38 @@ $ rad patch comment aa45913 --edit 686ec1c --message 'I cannot wait to get back
And if we really made a mistake, then we can redact the comment entirely:
```
-$ rad patch comment aa45913 --redact f4336e4 --no-announce
-✓ Redacted comment f4336e42daf76342f787d574b5ee779d89d05c7a
+$ rad patch comment 26ba061 --redact e991532 --no-announce
+✓ Redacted comment e99153259a09f5a15e385e531a5943d314245db1
```
Now, let's checkout the patch that we just created:
```
-$ rad patch checkout aa45913
-✓ Switched to branch patch/aa45913 at revision 6e5a3b7
-✓ Branch patch/aa45913 setup to track rad/patches/aa45913e757cacd46972733bddee5472c78fa32a
+$ rad patch checkout 26ba061
+✓ Switched to branch patch/26ba061 at revision d0013e3
+✓ Branch patch/26ba061 setup to track rad/patches/26ba0615c6e911344ee61d53241a2903c5bf8623
```
We can also add a review verdict as such:
```
-$ rad patch review aa45913 --accept --no-message --no-announce
-✓ Patch aa45913 accepted
+$ rad patch review 26ba061 --accept --no-message --no-announce
+✓ Patch 26ba061 accepted
```
Showing the patch list now will reveal the favorable verdict:
```
-$ rad patch show aa45913
+$ rad patch show 26ba061
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch aa45913e757cacd46972733bddee5472c78fa32a │
+│ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 │
│ Author alice (you) │
│ Labels fun │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
-│ Branches flux-capacitor-power, patch/aa45913 │
+│ Branches flux-capacitor-power, patch/26ba061 │
│ Commits ahead 2, behind 0 │
│ Status open │
│ │
@@ -204,32 +204,32 @@ $ rad patch show aa45913
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision aa45913 @ [.. ]..3e674d1 by alice (you) now │
-│ ↑ Revision 6e5a3b7 @ [.. ]..27857ec by alice (you) now │
+│ ● Revision 26ba061 @ [..]..3e674d1 by alice (you) now │
+│ ↑ Revision d0013e3 @ f2de534..27857ec by alice (you) now │
│ └─ ✓ accepted by alice (you) now │
╰──────────────────────────────────────────────────────────╯
$ rad patch list
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● aa45913 Define power requirements alice (you) ✓ 27857ec +0 -0 now fun │
+│ ● 26ba061 Define power requirements alice (you) ✓ 27857ec +0 -0 now fun │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
```
If you make a mistake on the patch description, you can always change it!
```
-$ rad patch edit aa45913 --message "Define power requirements" --message "Add requirements file" --no-announce
-$ rad patch show aa45913
+$ rad patch edit 26ba061 --message "Define power requirements" --message "Add requirements file" --no-announce
+$ rad patch show 26ba061
╭──────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch aa45913e757cacd46972733bddee5472c78fa32a │
+│ Patch 26ba0615c6e911344ee61d53241a2903c5bf8623 │
│ Author alice (you) │
│ Labels fun │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
-│ Branches flux-capacitor-power, patch/aa45913 │
+│ Branches flux-capacitor-power, patch/26ba061 │
│ Commits ahead 2, behind 0 │
│ Status open │
│ │
@@ -238,8 +238,8 @@ $ rad patch show aa45913
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────┤
-│ ● Revision aa45913 @ [.. ]..3e674d1 by alice (you) now │
-│ ↑ Revision 6e5a3b7 @ [.. ]..27857ec by alice (you) now │
+│ ● Revision 26ba061 @ [..]..3e674d1 by alice (you) now │
+│ ↑ Revision d0013e3 @ f2de534..27857ec by alice (you) now │
│ └─ ✓ accepted by alice (you) now │
╰──────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-publish.md b/crates/radicle-cli/examples/rad-publish.md
index c3872e5d8c..2f67d62190 100644
--- a/crates/radicle-cli/examples/rad-publish.md
+++ b/crates/radicle-cli/examples/rad-publish.md
@@ -15,7 +15,7 @@ public
The repository is now in our inventory:
```
$ rad node inventory
-rad:z2ug5mwNKZB8KGpBDRTrWHAMbvHCu
+rad:z2PZv5hqSvKC6A5cTQrF5VXwG97Q2
```
If we try to publish again, we get an error:
@@ -34,12 +34,12 @@ repository private again __will not_ be replicated.
```
$ rad id update --visibility private --title "Privatise" --description "Reverting the rad publish event"
-✓ Identity revision 774cc1e72641d97d7dc9377745b7f454a9171747 created
+✓ Identity revision 64213cccd6bcb7b36fb03bb02b96c4439cdb73ca created
╭────────────────────────────────────────────────────────────────────────╮
│ Title Privatise │
-│ Revision 774cc1e72641d97d7dc9377745b7f454a9171747 │
-│ Parent cecb16c9bebf35cfc4130f17efe6424f8ac71d66 │
-│ Blob 88f759a4d46e9535766fccec0cbfe1fed6160b1a │
+│ Revision 64213cccd6bcb7b36fb03bb02b96c4439cdb73ca │
+│ Parent e2c923cc39373a95b8df231843288c402e51360d │
+│ Blob 63b5274c1fbf5b39f0f76eb16192b6aebd45e67f │
│ Author did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi │
│ State accepted │
│ Quorum yes │
@@ -49,20 +49,30 @@ $ rad id update --visibility private --title "Privatise" --description "Revertin
│ ✓ did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi alice (you) │
╰────────────────────────────────────────────────────────────────────────╯
-@@ -1,13 +1,16 @@
+@@ -1,23 +1,26 @@
{
+ "version": 2,
"payload": {
+ "xyz.radicle.crefs": {
+ "rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 1
+ }
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
+ }
+ },
"xyz.radicle.project": {
- "defaultBranch": "master",
"description": "radicle heartwood protocol & stack",
"name": "heartwood"
}
},
"delegates": [
"did:key:z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi"
- ],
-- "threshold": 1
-+ "threshold": 1,
+- ]
++ ],
+ "visibility": {
+ "type": "private"
+ }
diff --git a/crates/radicle-cli/examples/rad-push-and-pull-patches.md b/crates/radicle-cli/examples/rad-push-and-pull-patches.md
index 0ca7df085f..d495d34c22 100644
--- a/crates/radicle-cli/examples/rad-push-and-pull-patches.md
+++ b/crates/radicle-cli/examples/rad-push-and-pull-patches.md
@@ -12,35 +12,35 @@ $ git checkout -b alice/1 -q
$ git rev-parse HEAD
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
$ git checkout master -q
-$ rad patch checkout d004b67
-✓ Switched to branch patch/d004b67 at revision d004b67
-✓ Branch patch/d004b67 setup to track rad/patches/d004b67355456c46de10c0d287e4a791ad1a6945
+$ rad patch checkout 6118f2b
+✓ Switched to branch patch/6118f2b at revision 6118f2b
+✓ Branch patch/6118f2b setup to track rad/patches/6118f2b18790045d75584169043ebfeb80c67dd4
$ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote bob@z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk added
✓ Remote-tracking branch bob@z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk/master created for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ git checkout master -q
$ cat .git/FETCH_HEAD
-f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/d004b67355456c46de10c0d287e4a791ad1a6945' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 not-for-merge branch 'master' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/6118f2b18790045d75584169043ebfeb80c67dd4' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
$ git rev-parse master
f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
```
``` ~alice (stderr)
-$ git checkout patch/d004b67 -q
+$ git checkout patch/6118f2b -q
$ git commit --allow-empty -m "Changes #2" -q
$ git push
-✓ Patch d004b67 updated to revision 2eb705c3da98e05c083df15be5b1bd6856a0bd77
-To compare against your previous revision d004b67, run:
+✓ Patch 6118f2b updated to revision 5d11564eeea9256e3847879f60461fe07a6e2fb1
+To compare against your previous revision 6118f2b, run:
- git range-diff f2de534[..] 8d5f1ba[..] c2aaf1c[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc c2aaf1c4c36a6bacb64d3f15a310280b054a2213
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- * [new branch] patch/d004b67 -> patches/d004b67355456c46de10c0d287e4a791ad1a6945
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ * [new branch] patch/6118f2b -> patches/6118f2b18790045d75584169043ebfeb80c67dd4
```
``` ~bob
@@ -51,32 +51,32 @@ $ git push
``` ~alice (stderr)
$ git checkout master -q
$ git pull
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
- + c2aaf1c...8d5f1ba patches/d004b67355456c46de10c0d287e4a791ad1a6945 -> rad/patches/d004b67355456c46de10c0d287e4a791ad1a6945 (forced update)
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+ + c2aaf1c...8d5f1ba patches/6118f2b18790045d75584169043ebfeb80c67dd4 -> rad/patches/6118f2b18790045d75584169043ebfeb80c67dd4 (forced update)
$ git checkout - -q
$ git commit --allow-empty -m "Changes #3" -q
$ git push
-✓ Patch d004b67 updated to revision 7b5015a8dac188bb0d44a334aa68a51298750b07
-To compare against your previous revision d004b67, run:
+✓ Patch 6118f2b updated to revision 9560846e836bb2ed0b29dfb0dfe33c5d99098855
+To compare against your previous revision 6118f2b, run:
- git range-diff f2de534[..] 8d5f1ba[..] d9f8caf[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc d9f8caf6e25a16e82e9a4df9ebe256ce6e727aa4
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- c2aaf1c..d9f8caf patch/d004b67 -> patches/d004b67355456c46de10c0d287e4a791ad1a6945
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ c2aaf1c..d9f8caf patch/6118f2b -> patches/6118f2b18790045d75584169043ebfeb80c67dd4
```
``` ~alice
$ cat .git/FETCH_HEAD
-f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/d004b67355456c46de10c0d287e4a791ad1a6945' of rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 branch 'master' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+8d5f1bae4b69d8e3f6cbfc6f4bd675ed19990afc not-for-merge branch 'patches/6118f2b18790045d75584169043ebfeb80c67dd4' of rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
```
``` ~bob (stderr)
$ git checkout master -q
$ git pull
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
- + c2aaf1c...8d5f1ba patches/d004b67355456c46de10c0d287e4a791ad1a6945 -> rad/patches/d004b67355456c46de10c0d287e4a791ad1a6945 (forced update)
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
+ + c2aaf1c...8d5f1ba patches/6118f2b18790045d75584169043ebfeb80c67dd4 -> rad/patches/6118f2b18790045d75584169043ebfeb80c67dd4 (forced update)
```
``` ~bob
diff --git a/crates/radicle-cli/examples/rad-review-by-hunk.md b/crates/radicle-cli/examples/rad-review-by-hunk.md
index d21b15e1d7..0c20cb6125 100644
--- a/crates/radicle-cli/examples/rad-review-by-hunk.md
+++ b/crates/radicle-cli/examples/rad-review-by-hunk.md
@@ -61,8 +61,8 @@ $ git commit -q -m "Update files"
``` (stderr)
$ git push rad HEAD:refs/patches
-✓ Patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+✓ Patch 3cb70d8de3d4c2285ae27017981a104362639042 opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
* [new reference] HEAD -> refs/patches
```
@@ -70,7 +70,7 @@ Finally, we do a review of the patch by hunk. The output of this command should
match `git diff master -W100% -U5 --patience`:
```
-$ rad patch review --patch -U5 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
+$ rad patch review --patch -U5 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
╭──────────────────────╮
│ .gitignore ❲deleted❳ │
├──────────────────────┤
@@ -117,8 +117,8 @@ $ rad patch review --patch -U5 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-ann
Now let's accept these hunks one by one..
```
-$ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
╭──────────────────────╮
│ .gitignore ❲deleted❳ │
├──────────────────────┤
@@ -128,8 +128,8 @@ $ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1
✓ Updated brain to a5fccf0e977225ff13c3f74c43faf4cb679bf835
```
```
-$ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
╭──────────────────────────────────────────────────────────╮
│ DISCLAIMER.txt ❲created❳ │
├──────────────────────────────────────────────────────────┤
@@ -139,8 +139,8 @@ $ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1
✓ Updated brain to 2cdb82ea726e64d3b52847c7699d0d4759198f5c
```
```
-$ rad patch review --patch --accept -U3 --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept -U3 --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
╭─────────────────────────────╮
│ MENU.txt │
├─────────────────────────────┤
@@ -155,8 +155,8 @@ $ rad patch review --patch --accept -U3 --hunk 1 7a2ac7e2841cc1e7394f99f107555a4
✓ Updated brain to d4aecbb859a802a3215def0b538358bf63593953
```
```
-$ rad patch review --patch --accept -U3 --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept -U3 --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
╭───────────────────────────────────────╮
│ MENU.txt │
├───────────────────────────────────────┤
@@ -172,8 +172,8 @@ $ rad patch review --patch --accept -U3 --hunk 1 7a2ac7e2841cc1e7394f99f107555a4
```
```
-$ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
╭────────────────────────────────────────────────────╮
│ INSTRUCTIONS.txt -> notes/INSTRUCTIONS.txt ❲moved❳ │
╰────────────────────────────────────────────────────╯
@@ -181,7 +181,7 @@ $ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1
```
```
-$ rad patch review --patch --accept --hunk 1 7a2ac7e2841cc1e7394f99f107555a499b1d3f23 --no-announce
-✓ Loaded existing review ([..]) for patch 7a2ac7e2841cc1e7394f99f107555a499b1d3f23
+$ rad patch review --patch --accept --hunk 1 3cb70d8de3d4c2285ae27017981a104362639042 --no-announce
+✓ Loaded existing review ([..]) for patch 3cb70d8de3d4c2285ae27017981a104362639042
✓ All hunks have been reviewed
```
diff --git a/crates/radicle-cli/examples/rad-seed-and-follow.md b/crates/radicle-cli/examples/rad-seed-and-follow.md
index a01b224563..bfe906f85a 100644
--- a/crates/radicle-cli/examples/rad-seed-and-follow.md
+++ b/crates/radicle-cli/examples/rad-seed-and-follow.md
@@ -21,8 +21,8 @@ $ rad follow
Now let's seed one of Eve's repositories:
```
-$ rad seed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope followed --no-fetch
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+$ rad seed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope followed --no-fetch
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
```
We can list the repositories we are seeding by omitting the RID:
@@ -32,6 +32,6 @@ $ rad seed
╭─────────────────────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├─────────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji Error determining name. allow followed │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G Error determining name. allow followed │
╰─────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-seed-many.md b/crates/radicle-cli/examples/rad-seed-many.md
index 96e946e059..d855d79771 100644
--- a/crates/radicle-cli/examples/rad-seed-many.md
+++ b/crates/radicle-cli/examples/rad-seed-many.md
@@ -3,11 +3,9 @@ same time, where each repository specified will be fetched (unless `--no-fetch`
is used):
```
-$ rad seed rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm
-✓ Seeding policy updated for rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW with scope 'followed'
-Fetching rad:z3Rry7rpdWuGpfjPYGzdJKQADsoNW from the network, found 1 potential seed(s).
-✓ Target met: 1 seed(s)
-✓ Seeding policy updated for rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm with scope 'followed'
-Fetching rad:z3zTnCfi6cVSZG8eCGn6AMDypgAPm from the network, found 1 potential seed(s).
-✓ Target met: 1 seed(s)
+$ rad seed rad:z4MWZ4byNSpmGBdSiEJ8ABNDY7qdG rad:z3LZFDDTVnYU7GrenyRYzNaviFF5u
+✓ Seeding policy updated for rad:z4MWZ4byNSpmGBdSiEJ8ABNDY7qdG with scope 'followed'
+✗ Error: no candidate seeds were found to fetch from
+✓ Seeding policy updated for rad:z3LZFDDTVnYU7GrenyRYzNaviFF5u with scope 'followed'
+✗ Error: no candidate seeds were found to fetch from
```
diff --git a/crates/radicle-cli/examples/rad-seed-scope.md b/crates/radicle-cli/examples/rad-seed-scope.md
index 2652fc7db5..459bd0e064 100644
--- a/crates/radicle-cli/examples/rad-seed-scope.md
+++ b/crates/radicle-cli/examples/rad-seed-scope.md
@@ -1,38 +1,38 @@
By default `rad seed` should add a seeding policy with the `followed` scope:
```
-$ rad seed --no-fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'followed'
+$ rad seed --no-fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'followed'
$ rad seed
╭─────────────────────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├─────────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji Error determining name. allow followed │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G Error determining name. allow followed │
╰─────────────────────────────────────────────────────────────────────────────────╯
```
The policy can be updated by explicitly specifying a different scope:
```
-$ rad seed --no-fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --scope all
-✓ Seeding policy updated for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all'
+$ rad seed --no-fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --scope all
+✓ Seeding policy updated for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'all'
$ rad seed
╭──────────────────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├──────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji Error determining name. allow all │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G Error determining name. allow all │
╰──────────────────────────────────────────────────────────────────────────────╯
```
Running `rad seed` again without an explicit scope parameter should not change the existing policy:
```
-$ rad seed --no-fetch rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy exists for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji with scope 'all'
+$ rad seed --no-fetch rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy exists for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G with scope 'all'
$ rad seed
╭──────────────────────────────────────────────────────────────────────────────╮
│ Repository Name Policy Scope │
├──────────────────────────────────────────────────────────────────────────────┤
-│ rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji Error determining name. allow all │
+│ rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G Error determining name. allow all │
╰──────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-sync.md b/crates/radicle-cli/examples/rad-sync.md
index 8b181cdf91..71da0120d7 100644
--- a/crates/radicle-cli/examples/rad-sync.md
+++ b/crates/radicle-cli/examples/rad-sync.md
@@ -15,9 +15,9 @@ $ rad sync status --sort-by alias
╭───────────────────────────────────────────────────╮
│ Node ID Alias ? SigRefs Timestamp │
├───────────────────────────────────────────────────┤
-│ (you) alice ! 1d8285b [..] │
-│ z6Mkt67…v4N1tRk bob ✗ 55be805 [..] │
-│ z6Mkux1…nVhib7Z eve ✗ 55be805 [..] │
+│ (you) alice ! a1cd7ae now │
+│ z6Mkt67…v4N1tRk bob ✗ 65ca22e now │
+│ z6Mkux1…nVhib7Z eve ✗ 65ca22e now │
╰───────────────────────────────────────────────────╯
```
@@ -37,9 +37,9 @@ $ rad sync status --sort-by alias
╭───────────────────────────────────────────────────╮
│ Node ID Alias ? SigRefs Timestamp │
├───────────────────────────────────────────────────┤
-│ (you) alice ✓ 1d8285b [..] │
-│ z6Mkt67…v4N1tRk bob ✓ 1d8285b [..] │
-│ z6Mkux1…nVhib7Z eve ✓ 1d8285b [..] │
+│ (you) alice ✓ a1cd7ae now │
+│ z6Mkt67…v4N1tRk bob ✓ a1cd7ae now │
+│ z6Mkux1…nVhib7Z eve ✓ a1cd7ae now │
╰───────────────────────────────────────────────────╯
```
@@ -55,7 +55,7 @@ We can also use the `--fetch` option to only fetch objects:
```
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
@@ -65,7 +65,7 @@ Specifying both `--fetch` and `--announce` is equivalent to specifying none:
```
$ rad sync --fetch --announce
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 2 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
@@ -76,7 +76,7 @@ It's also possible to use the `--seed` flag to only sync with a specific node:
```
$ rad sync --fetch --seed z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 3 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 3 potential seed(s).
✓ Target met: 1 preferred seed(s).
🌱 Fetched from z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
```
@@ -90,7 +90,7 @@ $ rad issue open --title "Test `rad sync --replicas`" --description "Check that
```
$ rad sync --replicas 1
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 2 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 2 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6Mkux1aUQD2voWWukVb5nNUR7thrHveQG4pDQua8nVhib7Z
✓ Synced with 1 seed(s)
@@ -127,7 +127,7 @@ Fetching rad:z39mP9rQAaGmERfUMPULfPUi473tY from the network, found 1 potential s
Also note that you cannot sync an unseeded repo:
```
$ rad unseed rad:z39mP9rQAaGmERfUMPULfPUi473tY
-[...]
+[..]
```
``` (fail)
$ rad sync rad:z39mP9rQAaGmERfUMPULfPUi473tY
diff --git a/crates/radicle-cli/examples/rad-unseed-many.md b/crates/radicle-cli/examples/rad-unseed-many.md
index edeca073f4..0c20df61ab 100644
--- a/crates/radicle-cli/examples/rad-unseed-many.md
+++ b/crates/radicle-cli/examples/rad-unseed-many.md
@@ -8,15 +8,15 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
-│ nixpkgs rad:zyFFr2iwoTEfNF4jGNZHuoy7odMh public f2de534 Home for Nix Packages │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
+│ nixpkgs rad:z4TvK2n84TLVirqvccp4JFnfsJ84D public f2de534 Home for Nix Packages │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
We could stop seeding them if we didn't want other nodes to fetch them from us:
```
-$ rad unseed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji rad:zyFFr2iwoTEfNF4jGNZHuoy7odMh
-✓ Seeding policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji removed
-✓ Seeding policy for rad:zyFFr2iwoTEfNF4jGNZHuoy7odMh removed
+$ rad unseed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G rad:z4TvK2n84TLVirqvccp4JFnfsJ84D
+✓ Seeding policy for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G removed
+✓ Seeding policy for rad:z4TvK2n84TLVirqvccp4JFnfsJ84D removed
```
diff --git a/crates/radicle-cli/examples/rad-unseed.md b/crates/radicle-cli/examples/rad-unseed.md
index f258e51e20..08ad921c54 100644
--- a/crates/radicle-cli/examples/rad-unseed.md
+++ b/crates/radicle-cli/examples/rad-unseed.md
@@ -5,15 +5,15 @@ $ rad ls
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji public f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G public f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
We could stop seeding it if we didn't want other nodes to fetch it from us:
```
-$ rad unseed rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji
-✓ Seeding policy for rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji removed
+$ rad unseed rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G
+✓ Seeding policy for rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G removed
```
Now, if we run `rad ls`, we see it's gone:
@@ -32,7 +32,7 @@ $ rad ls --all
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Name RID Visibility Head Description │
├───────────────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ heartwood rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji local f2de534 Radicle Heartwood Protocol & Stack │
+│ heartwood rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G local f2de534 Radicle Heartwood Protocol & Stack │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
diff --git a/crates/radicle-cli/examples/rad-watch.md b/crates/radicle-cli/examples/rad-watch.md
index 39e3fc841e..ac10465a5e 100644
--- a/crates/radicle-cli/examples/rad-watch.md
+++ b/crates/radicle-cli/examples/rad-watch.md
@@ -16,5 +16,5 @@ $ git push rad master
```
``` ~bob
-$ rad watch --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji --node z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --ref 'refs/heads/master' --target e09c4dc1b54443ceea715ea648afecdcfd1dd7d0 --interval 500
+$ rad watch --repo rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G --node z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi --ref 'refs/heads/master' --target e09c4dc1b54443ceea715ea648afecdcfd1dd7d0 --interval 500
```
diff --git a/crates/radicle-cli/examples/workflow/3-issues.md b/crates/radicle-cli/examples/workflow/3-issues.md
index 895246c1d5..a220231a14 100644
--- a/crates/radicle-cli/examples/workflow/3-issues.md
+++ b/crates/radicle-cli/examples/workflow/3-issues.md
@@ -7,7 +7,7 @@ Let's say the new car you are designing with your peers has a problem with its f
$ rad issue open --title "flux capacitor underpowered" --description "Flux capacitor power requirements exceed current supply" --no-announce
╭─────────────────────────────────────────────────────────╮
│ Title flux capacitor underpowered │
-│ Issue 9037b7a42323d4b79e6a48b7d05d3bbaae11d69b │
+│ Issue e7545692903f2edce37b4819d1321d26d3e37f0b │
│ Author bob (you) │
│ Status open │
│ │
@@ -22,7 +22,7 @@ $ rad issue list
╭──────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Labels Assignees Opened │
├──────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● 9037b7a flux capacitor underpowered bob (you) now │
+│ ● e754569 flux capacitor underpowered bob (you) now │
╰──────────────────────────────────────────────────────────────────────────────────────────╯
```
@@ -31,6 +31,6 @@ found an important detail about the car's power requirements. It will help
whoever works on a fix.
```
-$ rad issue comment 9037b7a42323d4b79e6a48b7d05d3bbaae11d69b --message 'The flux capacitor needs 1.21 Gigawatts' -q --no-announce
-400cb155f512b4880858bb05f935104c34167b28
+$ rad issue comment e7545692903f2edce37b4819d1321d26d3e37f0b --message 'The flux capacitor needs 1.21 Gigawatts' -q --no-announce
+6034d6984974be72678e2a3234e230a546ea12ee
```
diff --git a/crates/radicle-cli/examples/workflow/4-patching-contributor.md b/crates/radicle-cli/examples/workflow/4-patching-contributor.md
index d9d1d99e3c..0b624876b6 100644
--- a/crates/radicle-cli/examples/workflow/4-patching-contributor.md
+++ b/crates/radicle-cli/examples/workflow/4-patching-contributor.md
@@ -26,8 +26,8 @@ Once the code is ready, we open a patch with our changes.
``` (stderr)
$ git push rad -o no-sync -o patch.message="Define power requirements" -o patch.message="See details." HEAD:refs/patches
-✓ Patch e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 opened
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+✓ Patch 466ea167f4fc46f425967ce02fcee337c0597fcb opened
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
* [new reference] HEAD -> refs/patches
```
@@ -38,15 +38,15 @@ $ rad patch
╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ● ID Title Author Reviews Head + - Updated Labels │
├─────────────────────────────────────────────────────────────────────────────────────────────────┤
-│ ● e4934b6 Define power requirements bob (you) - 3e674d1 +0 -0 now │
+│ ● 466ea16 Define power requirements bob (you) - 3e674d1 +0 -0 now │
╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
-$ rad patch show e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+$ rad patch show 466ea167f4fc46f425967ce02fcee337c0597fcb
╭────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 │
+│ Patch 466ea167f4fc46f425967ce02fcee337c0597fcb │
│ Author bob (you) │
│ Head 3e674d1a1df90807e934f9ae5da2591dd6848a33 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Branches flux-capacitor-power │
│ Commits ahead 1, behind 0 │
@@ -56,15 +56,15 @@ $ rad patch show e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
├────────────────────────────────────────────────────────┤
│ 3e674d1 Define power requirements │
├────────────────────────────────────────────────────────┤
-│ ● Revision e4934b6 @ [.. ]..3e674d1 by bob (you) now │
+│ ● Revision 466ea16 @ [..]..3e674d1 by bob (you) now │
╰────────────────────────────────────────────────────────╯
```
We can also confirm that the patch branch is in storage:
```
-$ git ls-remote rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk refs/heads/patches/*
-3e674d1a1df90807e934f9ae5da2591dd6848a33 refs/heads/patches/e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+$ git ls-remote rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk refs/heads/patches/*
+3e674d1a1df90807e934f9ae5da2591dd6848a33 refs/heads/patches/466ea167f4fc46f425967ce02fcee337c0597fcb
```
Wait, let's add a README too! Just for fun.
@@ -79,19 +79,19 @@ $ git commit --message "Add README, just for the fun"
```
``` (stderr) RAD_SOCKET=/dev/null
$ git push -o patch.message="Add README, just for the fun"
-✓ Patch e4934b6 updated to revision 773b9aab58b11e9fa83d0ed0baca2bea6ff889c9
-To compare against your previous revision e4934b6, run:
+✓ Patch 466ea16 updated to revision 56be6ed00cfed892e4e18f79ae69a9e62a4307d2
+To compare against your previous revision 466ea16, run:
- git range-diff f2de534[..] 3e674d1[..] 27857ec[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 3e674d1a1df90807e934f9ae5da2591dd6848a33 27857ec9eb04c69cacab516e8bf4b5fd36090f66
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
- 3e674d1..27857ec flux-capacitor-power -> patches/e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
+ 3e674d1..27857ec flux-capacitor-power -> patches/466ea167f4fc46f425967ce02fcee337c0597fcb
```
And let's leave a quick comment for our team:
```
-$ rad patch comment e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 --message 'I cannot wait to get back to the 90s!' -q
-8c66f87afadc7c7c857f8bb92973c25f64e75776
+$ rad patch comment 466ea167f4fc46f425967ce02fcee337c0597fcb --message 'I cannot wait to get back to the 90s!' -q
+ecdbfa5d85bd8b9968431e1768924e916032b93a
✓ Synced with 1 seed(s)
```
diff --git a/crates/radicle-cli/examples/workflow/5-patching-maintainer.md b/crates/radicle-cli/examples/workflow/5-patching-maintainer.md
index a459df0262..e4324a137f 100644
--- a/crates/radicle-cli/examples/workflow/5-patching-maintainer.md
+++ b/crates/radicle-cli/examples/workflow/5-patching-maintainer.md
@@ -8,7 +8,7 @@ of this.
```
$ rad remote add z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk --name bob --sync --fetch
✓ Follow policy updated for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk (bob)
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
✓ Remote bob added
✓ Remote-tracking branch bob/master created for z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk
@@ -21,19 +21,19 @@ $ rad inbox --sort-by id
╭────────────────────────────────────────────────────────────────────────────╮
│ heartwood │
├────────────────────────────────────────────────────────────────────────────┤
-│ 001 ● 9037b7a flux capacitor underpowered issue open bob now │
-│ 002 ● e4934b6 Define power requirements patch open bob now │
+│ 001 ● e754569 flux capacitor underpowered issue open bob now │
+│ 002 ● 466ea16 Define power requirements patch open bob now │
╰────────────────────────────────────────────────────────────────────────────╯
$ git branch -r
- bob/patches/e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+ bob/patches/466ea167f4fc46f425967ce02fcee337c0597fcb
rad/master
-$ rad patch show e4934b6
+$ rad patch show 466ea16
╭──────────────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 │
+│ Patch 466ea167f4fc46f425967ce02fcee337c0597fcb │
│ Author bob z6Mkt67…v4N1tRk │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Commits ahead 2, behind 0 │
│ Status open │
@@ -43,8 +43,8 @@ $ rad patch show e4934b6
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────────────┤
-│ ● Revision e4934b6 @ [.. ]..3e674d1 by bob z6Mkt67…v4N1tRk now │
-│ ↑ Revision 773b9aa @ [.. ]..27857ec by bob z6Mkt67…v4N1tRk now │
+│ ● Revision 466ea16 @ [..]..3e674d1 by bob z6Mkt67…v4N1tRk now │
+│ ↑ Revision 56be6ed @ f2de534..27857ec by bob z6Mkt67…v4N1tRk now │
╰──────────────────────────────────────────────────────────────────╯
```
@@ -54,35 +54,35 @@ way will tell others about the corrections we needed before merging the
changes.
```
-$ rad patch checkout e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
-✓ Switched to branch patch/e4934b6 at revision 773b9aa
-✓ Branch patch/e4934b6 setup to track rad/patches/e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+$ rad patch checkout 466ea167f4fc46f425967ce02fcee337c0597fcb
+✓ Switched to branch patch/466ea16 at revision 56be6ed
+✓ Branch patch/466ea16 setup to track rad/patches/466ea167f4fc46f425967ce02fcee337c0597fcb
$ git mv REQUIREMENTS REQUIREMENTS.md
$ git commit -m "Use markdown for requirements"
-[patch/e4934b6 f567f69] Use markdown for requirements
+[patch/466ea16 f567f69] Use markdown for requirements
1 file changed, 0 insertions(+), 0 deletions(-)
rename REQUIREMENTS => REQUIREMENTS.md (100%)
```
``` (stderr)
$ git push rad -o no-sync -o patch.message="Use markdown for requirements"
-✓ Patch e4934b6 updated to revision 9d62420e779e5cfe1dc02c51eddec9a0907aa844
-To compare against your previous revision 773b9aa, run:
+✓ Patch 466ea16 updated to revision 03f1ec0b2942fc67cb2895dc8c54f8864a852a56
+To compare against your previous revision 56be6ed, run:
- git range-diff f2de534[..] 27857ec[..] f567f69[..]
+ git range-diff f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354 27857ec9eb04c69cacab516e8bf4b5fd36090f66 f567f695d25b4e8fb63b5f5ad2a584529826e908
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
- * [new branch] patch/e4934b6 -> patches/e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+ * [new branch] patch/466ea16 -> patches/466ea167f4fc46f425967ce02fcee337c0597fcb
```
Great, all fixed up, lets accept and merge the code.
```
-$ rad patch review e4934b6 --revision 9d62420 --accept
-✓ Patch e4934b6 accepted
+$ rad patch review 466ea16 --revision 03f1ec0 --accept
+✓ Patch 466ea16 accepted
✓ Synced with 1 seed(s)
$ git checkout master
Your branch is up to date with 'rad/master'.
-$ git merge patch/e4934b6
+$ git merge patch/466ea16
Updating f2de534..f567f69
Fast-forward
README.md | 0
@@ -93,23 +93,23 @@ Fast-forward
```
``` (stderr)
$ git push rad master
-✓ Patch e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 merged at revision 9d62420
+✓ Patch 466ea167f4fc46f425967ce02fcee337c0597fcb merged at revision 03f1ec0
✓ Canonical reference refs/heads/master updated to target commit f567f695d25b4e8fb63b5f5ad2a584529826e908
✓ Synced with 1 seed(s)
-To rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+To rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..f567f69 master -> master
```
The patch is now merged and closed :).
```
-$ rad patch show e4934b6
+$ rad patch show 466ea16
╭──────────────────────────────────────────────────────────────────╮
│ Title Define power requirements │
-│ Patch e4934b6d9dbe01ce3c7fbb5b77a80d5f1dacdc46 │
+│ Patch 466ea167f4fc46f425967ce02fcee337c0597fcb │
│ Author bob z6Mkt67…v4N1tRk │
│ Head 27857ec9eb04c69cacab516e8bf4b5fd36090f66 │
-│ Base [.. ] │
+│ Base [..] │
│ Target master │
│ Commits ahead 0, behind 1 │
│ Status merged │
@@ -119,9 +119,9 @@ $ rad patch show e4934b6
│ 27857ec Add README, just for the fun │
│ 3e674d1 Define power requirements │
├──────────────────────────────────────────────────────────────────┤
-│ ● Revision e4934b6 @ [.. ]..3e674d1 by bob z6Mkt67…v4N1tRk now │
-│ ↑ Revision 773b9aa @ [.. ]..27857ec by bob z6Mkt67…v4N1tRk now │
-│ ↑ Revision 9d62420 @ [.. ]..f567f69 by alice (you) now │
+│ ● Revision 466ea16 @ [..]..3e674d1 by bob z6Mkt67…v4N1tRk now │
+│ ↑ Revision 56be6ed @ f2de534..27857ec by bob z6Mkt67…v4N1tRk now │
+│ ↑ Revision 03f1ec0 @ f2de534..f567f69 by alice (you) now │
│ └─ ✓ accepted by alice (you) now │
│ └─ ✓ merged by alice (you) │
╰──────────────────────────────────────────────────────────────────╯
@@ -137,7 +137,7 @@ Finally, we will close the issue that was opened for this
patch, marking it as solved:
```
-$ rad issue state 9037b7a --solved
-✓ Issue 9037b7a is now solved
+$ rad issue state e754569 --solved
+✓ Issue e754569 is now solved
✓ Synced with 1 seed(s)
```
diff --git a/crates/radicle-cli/examples/workflow/6-pulling-contributor.md b/crates/radicle-cli/examples/workflow/6-pulling-contributor.md
index a34dfbfe97..de4d84eda3 100644
--- a/crates/radicle-cli/examples/workflow/6-pulling-contributor.md
+++ b/crates/radicle-cli/examples/workflow/6-pulling-contributor.md
@@ -10,7 +10,7 @@ f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354
Then, we call `rad sync --fetch` to fetch from the maintainer:
```
$ rad sync --fetch
-Fetching rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji from the network, found 1 potential seed(s).
+Fetching rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G from the network, found 1 potential seed(s).
✓ Target met: 1 seed(s)
🌱 Fetched from z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
```
@@ -22,9 +22,9 @@ Your branch is up to date with 'rad/master'.
```
``` (stderr) RAD_SOCKET=/dev/null
$ git pull --all --ff
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G
f2de534..f567f69 master -> rad/master
-From rad://z42hL2jL4XNk6K8oHQaSWfMgCL7ji/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
+From rad://z4MmvDgm9DoJF6ecPSt55geCbNp4G/z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
f2de534..f567f69 master -> alice@z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/master
```
diff --git a/crates/radicle-cli/src/commands/clone.rs b/crates/radicle-cli/src/commands/clone.rs
index 9547918237..db1dd7a029 100644
--- a/crates/radicle-cli/src/commands/clone.rs
+++ b/crates/radicle-cli/src/commands/clone.rs
@@ -61,7 +61,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
.filter(|id| id != profile.id())
.collect::<Vec<_>>();
- let default_branch = repo.identity_doc()?.default_branch_name().ok();
+ let default_branch = doc.default_branch_name().ok();
let path = if !args.bare {
working.workdir().unwrap()
diff --git a/crates/radicle-cli/src/commands/id.rs b/crates/radicle-cli/src/commands/id.rs
index 9ff38f2bbf..64b8c45259 100644
--- a/crates/radicle-cli/src/commands/id.rs
+++ b/crates/radicle-cli/src/commands/id.rs
@@ -116,11 +116,14 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
edit,
} => {
let proposal = {
- let mut proposal = current.doc.clone().edit();
+ let proposal = current.doc.clone().edit();
let allow = allow.into_iter().collect::<BTreeSet<_>>();
let disallow = disallow.into_iter().collect::<BTreeSet<_>>();
- proposal.threshold = threshold.unwrap_or(proposal.threshold);
+ let proposal = match threshold {
+ Some(threshold) => update::threshold(proposal, threshold),
+ None => proposal,
+ };
let proposal = match visibility {
Some(edit) => update::visibility(proposal, edit),
@@ -136,14 +139,13 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
.into())
}
};
- let threshold = proposal.threshold;
let proposal = match update::delegates(proposal, delegates, rescind, &repo)? {
Ok(proposal) => proposal,
Err(errs) => {
term::error(format!("failed to verify delegates for {rid}"));
- term::error(format!(
- "the threshold of {threshold} delegates cannot be met.."
- ));
+ term::error(
+ "the required threshold of delegates cannot be met..".to_string(),
+ );
for e in errs {
print_delegate_verification_error(&e);
}
@@ -186,21 +188,44 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
}
return Ok(());
}
- let revision = update(title, description, proposal, &mut identity, &profile)?;
-
- if revision.is_accepted() && revision.parent == Some(current.id) {
- // Update the canonical head to point to the latest accepted revision.
- repo.set_identity_head_to(revision.id)?;
- }
- if args.quiet {
- term::println(revision.id);
- } else {
- term::success!(
- "Identity revision {} created",
- term::format::tertiary(revision.id)
+ propose(
+ title,
+ description,
+ proposal,
+ &mut identity,
+ ¤t,
+ &repo,
+ &profile,
+ args.quiet,
+ )?;
+ }
+ Command::Migrate { title, description } => {
+ let version = current.doc.version();
+ if version == doc::IDENTITY_VERSION {
+ anyhow::bail!(
+ "identity document is already at version {}",
+ doc::IDENTITY_VERSION
);
- print(&revision, ¤t, &repo, &profile)?;
}
+ let proposal = current.doc.migrated()?;
+
+ if !args.quiet {
+ term::println(term::format::italic(format!(
+ "Migrating identity document from version {version} to {}. \
+ Once adopted, this repository is no longer readable to older releases.",
+ doc::IDENTITY_VERSION
+ )));
+ }
+ propose(
+ title,
+ description,
+ proposal,
+ &mut identity,
+ ¤t,
+ &repo,
+ &profile,
+ args.quiet,
+ )?;
}
Command::List => {
let mut revisions =
@@ -503,6 +528,40 @@ and description.
Ok(result)
}
+/// Propose `doc` as a new revision, adopt it if the vote is already met, and
+/// report the outcome.
+#[allow(clippy::too_many_arguments)]
+fn propose(
+ title: Option<Title>,
+ description: Option<String>,
+ doc: Doc,
+ identity: &mut IdentityMut<
+ impl WriteRepository + cob::Store<Namespace = NodeId>,
+ impl crypto::Signer,
+ >,
+ current: &Revision,
+ repo: &radicle::storage::git::Repository,
+ profile: &Profile,
+ quiet: bool,
+) -> anyhow::Result<()> {
+ let revision = update(title, description, doc, identity, profile)?;
+
+ if revision.is_accepted() && revision.parent == Some(current.id) {
+ // Update the canonical head to point to the latest accepted revision.
+ repo.set_identity_head_to(revision.id)?;
+ }
+ if quiet {
+ term::println(revision.id);
+ } else {
+ term::success!(
+ "Identity revision {} created",
+ term::format::tertiary(revision.id)
+ );
+ print(&revision, current, repo, profile)?;
+ }
+ Ok(())
+}
+
fn update(
title: Option<Title>,
description: Option<String>,
diff --git a/crates/radicle-cli/src/commands/id/args.rs b/crates/radicle-cli/src/commands/id/args.rs
index 038a1e6256..00068f7c4a 100644
--- a/crates/radicle-cli/src/commands/id/args.rs
+++ b/crates/radicle-cli/src/commands/id/args.rs
@@ -220,6 +220,23 @@ pub(super) enum Command {
edit: bool,
},
+ /// Propose a revision that migrates the identity document to the current
+ /// version
+ ///
+ /// The migration is proposed like any other revision, so the delegates vote
+ /// on it. Once it is adopted, the repository is no longer readable to
+ /// releases that predate the new version.
+ #[clap(alias("m"))]
+ Migrate {
+ /// Set the title for the new proposal
+ #[arg(long)]
+ title: Option<Title>,
+
+ /// Set the description for the new proposal
+ #[arg(long)]
+ description: Option<String>,
+ },
+
/// Lists all proposed revisions to the identity document
#[clap(alias("l"))]
List,
diff --git a/crates/radicle-cli/src/commands/init.rs b/crates/radicle-cli/src/commands/init.rs
index ac95b979b0..7087086ec4 100644
--- a/crates/radicle-cli/src/commands/init.rs
+++ b/crates/radicle-cli/src/commands/init.rs
@@ -137,7 +137,8 @@ pub fn init(repo: raw::Repository, args: Args, profile: &profile::Profile) -> an
let mut spinner = term::spinner("Initializing…");
let mut push_cmd = String::from("git push");
- match radicle::rad::init(
+ match radicle::rad::init_at(
+ args.identity_version,
&repo,
name,
&description,
diff --git a/crates/radicle-cli/src/commands/init/args.rs b/crates/radicle-cli/src/commands/init/args.rs
index 88831bce1f..79fe064925 100644
--- a/crates/radicle-cli/src/commands/init/args.rs
+++ b/crates/radicle-cli/src/commands/init/args.rs
@@ -2,7 +2,7 @@ use std::path::PathBuf;
use clap::Parser;
use radicle::{
- identity::{Visibility, project::ProjectName},
+ identity::{Visibility, doc, project::ProjectName},
node::policy::Scope,
prelude::RepoId,
};
@@ -26,6 +26,14 @@ pub struct Args {
/// The default branch of the repository
#[arg(long = "default-branch")]
pub(super) branch: Option<String>,
+ /// The version of the identity document to write
+ ///
+ /// An older version keeps the repository readable to older releases, at the
+ /// cost of the features the newer version brings. Use `rad id migrate` to
+ /// move to the current version later.
+ #[arg(long = "identity-version", value_name = "VERSION")]
+ #[arg(default_value_t = doc::IDENTITY_VERSION)]
+ pub(super) identity_version: doc::Version,
/// Repository follow scope
#[arg(
long,
diff --git a/crates/radicle-cli/src/commands/publish.rs b/crates/radicle-cli/src/commands/publish.rs
index dc8d491d1c..641d962b54 100644
--- a/crates/radicle-cli/src/commands/publish.rs
+++ b/crates/radicle-cli/src/commands/publish.rs
@@ -42,7 +42,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
// Update identity document.
let doc = doc.clone().with_edits(|doc| {
- doc.visibility = Visibility::Public;
+ *doc.visibility_mut() = Visibility::Public;
})?;
// SAFETY: the `Title` here is guaranteed to be nonempty and does not
diff --git a/crates/radicle-cli/tests/commands.rs b/crates/radicle-cli/tests/commands.rs
index 8807212de3..4861694f53 100644
--- a/crates/radicle-cli/tests/commands.rs
+++ b/crates/radicle-cli/tests/commands.rs
@@ -99,7 +99,7 @@ fn rad_remote() {
let bob = environment.relay("bob");
let eve = environment.relay("eve");
let home = alice.home.clone();
- let rid = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let rid = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
// Set up a test repository.
environment.repository(&alice);
diff --git a/crates/radicle-cli/tests/commands/clone.rs b/crates/radicle-cli/tests/commands/clone.rs
index 3787c4fa3f..82d5b17259 100644
--- a/crates/radicle-cli/tests/commands/clone.rs
+++ b/crates/radicle-cli/tests/commands/clone.rs
@@ -179,7 +179,7 @@ fn rad_clone_connect() {
let alice = environment.node("alice");
let bob = environment.node("bob");
let mut eve = environment.node("eve");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
let ua = UserAgent::default();
let now = LocalTime::now().into();
diff --git a/crates/radicle-cli/tests/commands/git.rs b/crates/radicle-cli/tests/commands/git.rs
index 9ab6eb1e5f..d664ee40ef 100644
--- a/crates/radicle-cli/tests/commands/git.rs
+++ b/crates/radicle-cli/tests/commands/git.rs
@@ -10,7 +10,7 @@ fn git_push_diverge() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -53,7 +53,7 @@ fn git_push_converge() {
let alice = environment.node("alice");
let bob = environment.node("bob");
let eve = environment.node("eve");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -113,7 +113,7 @@ fn git_push_amend() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -158,7 +158,7 @@ fn git_push_rollback() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -265,7 +265,7 @@ fn git_push_canonical_lightweight_tags() {
let alice = environment.node("alice");
let bob = environment.node("bob");
- let rid = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let rid = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
fixtures::repository(environment.work(&alice));
@@ -311,7 +311,7 @@ fn git_push_canonical() {
let alice = environment.node("alice");
let bob = environment.node("bob");
- let rid = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let rid = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
fixtures::repository(environment.work(&alice));
diff --git a/crates/radicle-cli/tests/commands/id.rs b/crates/radicle-cli/tests/commands/id.rs
index 24f0e8c27c..09a1a31a63 100644
--- a/crates/radicle-cli/tests/commands/id.rs
+++ b/crates/radicle-cli/tests/commands/id.rs
@@ -15,7 +15,7 @@ fn rad_id() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -61,7 +61,7 @@ fn rad_id_threshold() {
let alice = environment.node("alice");
let bob = environment.node("bob");
let seed = environment.node("seed");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -117,7 +117,7 @@ fn rad_id_threshold_soft_fork() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -167,13 +167,62 @@ fn rad_id_update_delete_field() {
Environment::alice(["rad-init", "rad-id-update-delete-field"]);
}
+#[test]
+fn rad_id_migrate() {
+ Environment::alice(["rad-id-migrate"]);
+}
+
+#[test]
+fn rad_id_migrate_multi_delegate() {
+ let mut environment = Environment::new();
+ let alice = environment.node("alice");
+ let bob = environment.node("bob");
+ let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+
+ environment.repository(&alice);
+
+ test(
+ "examples/rad-init-v1.md",
+ environment.work(&alice),
+ Some(&alice.home),
+ [],
+ )
+ .unwrap();
+
+ let mut alice = alice.spawn();
+ let bob = bob.spawn();
+
+ alice.handle.seed(acme, Scope::All).unwrap();
+ alice.connect(&bob).converge([&bob]);
+
+ bob.fork(acme, environment.work(&bob)).unwrap();
+ bob.has_remote_of(&acme, &alice.id);
+ alice.has_remote_of(&acme, &bob.id);
+ alice.is_synced_with(&acme, &bob.id);
+
+ formula(&environment.tempdir(), "examples/rad-id-migrate-vote.md")
+ .unwrap()
+ .home(
+ "alice",
+ environment.work(&alice),
+ [("RAD_HOME", alice.home.path().display())],
+ )
+ .home(
+ "bob",
+ environment.work(&bob),
+ [("RAD_HOME", bob.home.path().display())],
+ )
+ .run()
+ .unwrap();
+}
+
#[test]
fn rad_id_multi_delegate() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
let eve = environment.node("eve");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -227,7 +276,7 @@ fn rad_id_unauthorized_delegate() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -281,7 +330,7 @@ fn rad_id_collaboration() {
let eve = environment.node("eve");
let seed = environment.seed("seed");
let distrustful = environment.seed("distrustful");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -382,7 +431,7 @@ fn rad_id_conflict() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
diff --git a/crates/radicle-cli/tests/commands/patch.rs b/crates/radicle-cli/tests/commands/patch.rs
index d908f46178..76e7d3d40c 100644
--- a/crates/radicle-cli/tests/commands/patch.rs
+++ b/crates/radicle-cli/tests/commands/patch.rs
@@ -46,7 +46,7 @@ fn rad_patch_checkout_force() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -156,7 +156,7 @@ fn rad_patch_delete() {
let alice = environment.relay("alice");
let bob = environment.relay("bob");
let seed = environment.relay("seed");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -211,7 +211,7 @@ fn rad_push_and_pull_patches() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
@@ -452,7 +452,7 @@ fn rad_patch_merge_unauthorized_branch() {
let mut environment = Environment::new();
let alice = environment.node("alice");
let bob = environment.node("bob");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
environment.repository(&alice);
diff --git a/crates/radicle-cli/tests/commands/remote.rs b/crates/radicle-cli/tests/commands/remote.rs
index 68407d3309..0805f29dbc 100644
--- a/crates/radicle-cli/tests/commands/remote.rs
+++ b/crates/radicle-cli/tests/commands/remote.rs
@@ -13,7 +13,7 @@ fn rad_remote() {
let bob = environment.relay("bob");
let eve = environment.relay("eve");
let home = alice.home.clone();
- let rid = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let rid = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
// Set up a test repository.
environment.repository(&alice);
diff --git a/crates/radicle-cli/tests/commands/sync.rs b/crates/radicle-cli/tests/commands/sync.rs
index d06f2e5641..4b50046d5b 100644
--- a/crates/radicle-cli/tests/commands/sync.rs
+++ b/crates/radicle-cli/tests/commands/sync.rs
@@ -68,7 +68,7 @@ fn rad_sync() {
let alice = environment.seed("alice");
let bob = environment.seed("bob");
let eve = environment.seed("eve");
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
radicle::test::fixtures::repository(working.join("acme"));
@@ -117,7 +117,7 @@ fn replication_via_seed() {
seeding_policy: DefaultSeedingPolicy::permissive(),
..crate::util::environment::config::relay("seed")
});
- let rid = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let rid = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
let mut alice = alice.spawn();
let mut bob = bob.spawn();
diff --git a/crates/radicle-cli/tests/commands/utility.rs b/crates/radicle-cli/tests/commands/utility.rs
index cbabfeb40e..37aa275e6b 100644
--- a/crates/radicle-cli/tests/commands/utility.rs
+++ b/crates/radicle-cli/tests/commands/utility.rs
@@ -75,7 +75,7 @@ fn rad_clean() {
let working = environment.tempdir().join("working");
// Set up a test project.
- let acme = RepoId::from_str("z42hL2jL4XNk6K8oHQaSWfMgCL7ji").unwrap();
+ let acme = RepoId::from_str("z4MmvDgm9DoJF6ecPSt55geCbNp4G").unwrap();
radicle::test::fixtures::repository(working.join("acme"));
test(
"examples/rad-init.md",
diff --git a/crates/radicle-fetch/src/state.rs b/crates/radicle-fetch/src/state.rs
index 8a8fb2120a..d7b60ef7fb 100644
--- a/crates/radicle-fetch/src/state.rs
+++ b/crates/radicle-fetch/src/state.rs
@@ -4,7 +4,7 @@ use std::time::Instant;
use gix_protocol::Handshake;
use radicle::crypto::PublicKey;
use radicle::git::{Oid, fmt::Qualified};
-use radicle::identity::{Did, Doc, DocError};
+use radicle::identity::{Doc, DocError, doc::DefaultBranchError};
use radicle::storage;
use radicle::storage::git::Repository;
@@ -62,6 +62,10 @@ pub mod error {
},
#[error("canonical 'refs/rad/id' is missing")]
MissingRadId,
+ #[error("failed to resolve default branch quorum from 'refs/rad/id': {0}")]
+ DefaultBranch(#[from] radicle::identity::doc::DefaultBranchError),
+ #[error("canonical 'refs/rad/id' has no rule matching its default branch")]
+ MissingBranchRule,
#[error(transparent)]
RefdbUpdate(#[from] repository::error::Update),
#[error(transparent)]
@@ -415,29 +419,55 @@ impl FetchState {
.canonical()?
.ok_or(error::Protocol::MissingRadId)?;
- let is_delegate = anchor.is_delegate(&Did::from(handle.local()));
- // TODO: not sure we should allow to block *any* peer from the
- // delegate set. We could end up ignoring delegates.
- let delegates = anchor
- .delegates()
+ // The canonical default branch — and the quorum required to establish
+ // it — is defined by the crefs rule that matches it. Fail closed: if the
+ // anchor's canonical references or default branch cannot be resolved, or
+ // no rule matches, abort the fetch rather than silently proceeding with
+ // a quorum of 1 (which would let a single delegate — or a seed serving a
+ // malformed 'refs/rad/id' — downgrade the required quorum).
+ let crefs = anchor.canonical_refs().map_err(DefaultBranchError::from)?;
+ let branch = anchor.default_branch()?;
+ let (_, branch_rule) = crefs
+ .rules()
+ .matches(&branch)
+ .next()
+ .ok_or(error::Protocol::MissingBranchRule)?;
+ let branch_threshold = usize::from(*branch_rule.threshold());
+
+ // The peers who vote on the canonical branch are the matched rule's
+ // `allowed` set — not the identity delegates — so that the threshold and
+ // the counted population come from the same rule. For the common
+ // `allow: delegates` rule this set is exactly the identity delegates; for
+ // an explicit `allow` set it may include non-delegates.
+ // TODO: not sure we should allow to block *any* peer from the voter set.
+ // We could end up ignoring voters.
+ let voters = branch_rule
+ .allowed()
.iter()
.filter(|id| !handle.is_blocked(id))
.map(|did| PublicKey::from(*did))
.collect::<BTreeSet<_>>();
- log::trace!("Identity delegates {delegates:?}");
+ log::trace!("Canonical branch voters {voters:?}");
- // The local peer does not need to count towards the threshold
- // since they must be valid already.
- let threshold = if is_delegate {
- anchor.threshold() - 1
+ // The local peer does not need to count towards the quorum since they
+ // must be valid already. Membership is checked against the rule's full
+ // `allowed` set, not the `voters` set above: `voters` has the local peer
+ // (which is always "blocked" from itself) and any blocked peers filtered
+ // out, so it must not be used to decide whether the local peer votes.
+ let is_voter = branch_rule
+ .allowed()
+ .iter()
+ .any(|did| PublicKey::from(*did) == *handle.local());
+ let threshold = if is_voter {
+ branch_threshold.saturating_sub(1)
} else {
- anchor.threshold()
+ branch_threshold
};
let signed_refs = self.run_special_refs(
handle,
handshake,
- delegates.clone(),
+ voters.clone(),
threshold,
&config.limit,
remote,
@@ -479,16 +509,16 @@ impl FetchState {
// non-pruned, fetched remotes here.
let mut remotes = BTreeSet::new();
- // The valid delegates start with all delegates that this peer
- // currently has valid references for
- let mut valid_delegates = handle
+ // The valid voters start with all branch voters that this peer
+ // currently has valid references for.
+ let mut valid_voters = handle
.repository()
.remote_ids()
.map_err(error::Protocol::RemoteIds)?
.filter_map(|id| id.ok())
- .filter(|id| delegates.contains(id))
+ .filter(|id| voters.contains(id))
.collect::<BTreeSet<_>>();
- let mut failed_delegates = BTreeSet::new();
+ let mut failed_voters = BTreeSet::new();
// TODO(finto): this might read better if it got its own
// private function.
@@ -498,7 +528,7 @@ impl FetchState {
continue;
}
- match (refs, delegates.contains(&remote)) {
+ match (refs, voters.contains(&remote)) {
(Ok(None), false) => {
log::debug!("Pruning non-delegate {remote} tips, missing 'rad/sigrefs'");
failures.push(sigrefs::Validation::MissingRadSigRefs(remote));
@@ -513,14 +543,14 @@ impl FetchState {
// previous `rad/sigrefs` but if this occurs with
// enough delegates also failing validation we
// would rather surface the issue and fail the fetch.
- valid_delegates.remove(&remote);
- failed_delegates.insert(remote);
+ valid_voters.remove(&remote);
+ failed_voters.insert(remote);
}
(Err(err), _) => {
log::debug!("Pruning {remote} tips due to: {err}");
self.prune(&remote);
- valid_delegates.remove(&remote);
- failed_delegates.insert(remote);
+ valid_voters.remove(&remote);
+ failed_voters.insert(remote);
failures.push(sigrefs::Validation::Read {
remote,
source: err,
@@ -540,8 +570,8 @@ impl FetchState {
});
if delegate {
- valid_delegates.remove(&remote);
- failed_delegates.insert(remote);
+ valid_voters.remove(&remote);
+ failed_voters.insert(remote);
}
self.prune(&remote);
@@ -648,11 +678,11 @@ impl FetchState {
if !fails.is_empty() {
log::debug!("Pruning delegate {remote} tips, due to validation failures");
self.prune(&remote);
- valid_delegates.remove(&remote);
- failed_delegates.insert(remote);
+ valid_voters.remove(&remote);
+ failed_voters.insert(remote);
failures.append(&mut fails)
} else {
- valid_delegates.insert(remote);
+ valid_voters.insert(remote);
remotes.insert(remote);
}
@@ -673,7 +703,7 @@ impl FetchState {
// N.b. only apply to Git repository if there are enough valid
// delegates that pass the threshold.
- if valid_delegates.len() >= threshold {
+ if valid_voters.len() >= threshold {
let applied = repository::update(
handle.repository(),
self.tips
@@ -695,7 +725,7 @@ impl FetchState {
);
Ok(FetchResult::Failed {
threshold,
- delegates: failed_delegates,
+ delegates: failed_voters,
validations: failures,
})
}
diff --git a/crates/radicle-node/src/test/simulator.rs b/crates/radicle-node/src/test/simulator.rs
index 9cf72594a3..0bb1de5313 100644
--- a/crates/radicle-node/src/test/simulator.rs
+++ b/crates/radicle-node/src/test/simulator.rs
@@ -400,7 +400,7 @@ where
}
Err(err) => panic!("Error fetching: {err}"),
}
- p.fetched(rid, nid, result);
+ p.fetched(rid, nid, result.map(Box::new));
}
}
while let Some(o) = p.next() {
diff --git a/crates/radicle-node/src/tests.rs b/crates/radicle-node/src/tests.rs
index d6253acca7..46944d37c7 100644
--- a/crates/radicle-node/src/tests.rs
+++ b/crates/radicle-node/src/tests.rs
@@ -494,7 +494,7 @@ fn announcement_rebroadcast_deduplicates() {
repo.doc.doc = repo
.doc
.doc
- .with_edits(|doc| doc.visibility = Visibility::Public)
+ .with_edits(|doc| *doc.visibility_mut() = Visibility::Public)
.unwrap();
amy.storage_mut().repos.insert(*rid, repo);
}
@@ -702,7 +702,7 @@ fn refs_announcement_relay_public() {
.doc
.doc
.with_edits(|doc| {
- doc.visibility = Visibility::Public; // Public repos are always gossiped.
+ *doc.visibility_mut() = Visibility::Public; // Public repos are always gossiped.
})
.unwrap();
amy.storage_mut().repos.insert(bob_inv[i], repo);
@@ -769,7 +769,7 @@ fn refs_announcement_relay_private() {
.doc
.doc
.with_edits(|doc| {
- doc.visibility = Visibility::Private { allow: [].into() };
+ *doc.visibility_mut() = Visibility::Private { allow: [].into() };
})
.unwrap();
repo
@@ -783,7 +783,7 @@ fn refs_announcement_relay_private() {
.doc
.doc
.with_edits(|doc| {
- doc.visibility = Visibility::Private {
+ *doc.visibility_mut() = Visibility::Private {
allow: [(*cid.nid()).into()].into(),
};
})
@@ -837,7 +837,7 @@ fn refs_announcement_subscribe_private() {
.doc
.doc
.with_edits(|doc| {
- doc.visibility = Visibility::Private {
+ *doc.visibility_mut() = Visibility::Private {
allow: [(*amy.nid()).into(), (*bob.nid()).into()].into(),
};
})
@@ -1523,7 +1523,11 @@ fn queued_fetch_max_capacity() {
amy.elapse(KEEP_ALIVE_DELTA);
// Finish the 1st fetch.
- amy.fetched(rid1, *bob.nid(), Ok(FetchResult::new(doc.clone())));
+ amy.fetched(
+ rid1,
+ *bob.nid(),
+ Ok(Box::new(FetchResult::new(doc.clone()))),
+ );
// Now the 1st fetch is done, the 2nd fetch is dequeued.
assert_eq!(amy.fetches().next(), Some((rid2, *bob.nid())));
@@ -1531,7 +1535,7 @@ fn queued_fetch_max_capacity() {
assert_matches!(amy.fetches().next(), None);
// Finish the 2nd fetch.
- amy.fetched(rid2, *bob.nid(), Ok(FetchResult::new(doc)));
+ amy.fetched(rid2, *bob.nid(), Ok(Box::new(FetchResult::new(doc))));
// Now the 2nd fetch is done, the 3rd fetch is dequeued.
assert_eq!(amy.fetches().next(), Some((rid3, *bob.nid())));
}
@@ -1587,7 +1591,7 @@ fn orphaned_fetch_blocks_repo_from_all_nodes() {
// Delivering the missing result (what the fix guarantees) clears the entry
// and the queued fetch from the other node proceeds.
- amy.fetched(rid, *bob.nid(), Ok(FetchResult::new(doc)));
+ amy.fetched(rid, *bob.nid(), Ok(Box::new(FetchResult::new(doc))));
assert_eq!(amy.fetches().next(), Some((rid, *cid.nid())));
}
@@ -1651,7 +1655,7 @@ fn queued_fetch_from_ann_same_rid() {
amy.fetched(
rid,
*bob.nid(),
- Ok(FetchResult {
+ Ok(Box::new(FetchResult {
updated: vec![RefUpdate::Created {
name: refname.clone(),
oid,
@@ -1660,7 +1664,7 @@ fn queued_fetch_from_ann_same_rid() {
namespaces: [*cid.nid()].into_iter().collect(),
clone: false,
doc: arbitrary::r#gen(1),
- }),
+ })),
);
// Now the 1st fetch is done, but the 2nd and 3rd fetches are redundant.
assert_matches!(amy.fetches().next(), None);
@@ -1710,7 +1714,7 @@ fn queued_fetch_from_command_same_rid() {
amy.elapse(KEEP_ALIVE_DELTA);
// Finish the 1st fetch.
- amy.fetched(rid1, nid, Ok(arbitrary::r#gen::<FetchResult>(1)));
+ amy.fetched(rid1, nid, Ok(Box::new(arbitrary::r#gen::<FetchResult>(1))));
// Now the 1st fetch is done, the 2nd fetch is dequeued.
let (rid, nid) = amy.fetches().next().unwrap();
assert_eq!(rid, rid1);
@@ -1720,7 +1724,7 @@ fn queued_fetch_from_command_same_rid() {
assert_matches!(amy.fetches().next(), None);
// Finish the 2nd fetch.
- amy.fetched(rid1, nid, Ok(arbitrary::r#gen::<FetchResult>(1)));
+ amy.fetched(rid1, nid, Ok(Box::new(arbitrary::r#gen::<FetchResult>(1))));
// Now the 2nd fetch is done, the 3rd fetch is dequeued.
assert_matches!(amy.fetches().next(), Some((rid, nid)) if rid == rid1 && peers.remove(&nid));
// All fetches were initiated.
@@ -1878,21 +1882,21 @@ fn prop_inventory_exchange_dense() {
AMY,
amy_inv
.clone()
- .map(|doc| doc.visibility = Visibility::Public),
+ .map(|doc| *doc.visibility_mut() = Visibility::Public),
);
let mut bob = Peer::with_storage(
"bob",
BOB,
bob_inv
.clone()
- .map(|doc| doc.visibility = Visibility::Public),
+ .map(|doc| *doc.visibility_mut() = Visibility::Public),
);
let mut cid = Peer::with_storage(
"cid",
CID,
cid_inv
.clone()
- .map(|doc| doc.visibility = Visibility::Public),
+ .map(|doc| *doc.visibility_mut() = Visibility::Public),
);
let mut routing = RandomMap::with_hasher(rng.clone().into());
diff --git a/crates/radicle-node/src/tests/e2e.rs b/crates/radicle-node/src/tests/e2e.rs
index affcb6c02f..a03161ff6d 100644
--- a/crates/radicle-node/src/tests/e2e.rs
+++ b/crates/radicle-node/src/tests/e2e.rs
@@ -195,7 +195,7 @@ fn public_to_private_to_public_replay() {
.unwrap()
.doc
.with_edits(|doc| {
- doc.visibility = Visibility::private([]);
+ *doc.visibility_mut() = Visibility::private([]);
})
.unwrap();
let private_rev = identity
@@ -1567,12 +1567,8 @@ fn missing_delegate_default_branch() {
// Helper to assert that Bob's default branch is not in storage
let assert_bobs_default_is_missing = |repo: &Repository| {
- let doc = repo.identity_doc().unwrap();
- let project = doc.project().unwrap().unwrap();
- let default_branch = repo.reference(
- &bob_key,
- &radicle::git::refs::branch(project.default_branch()),
- );
+ let branch_name = repo.default_branch_name().unwrap();
+ let default_branch = repo.reference(&bob_key, &radicle::git::refs::branch(&branch_name));
assert!(matches!(
default_branch,
Err(e) if e.is_not_found()
@@ -1895,8 +1891,8 @@ fn fetch_emits_canonical_ref_update() {
let default_branch: git::fmt::Qualified = {
let repo = alice.storage.repository(rid).unwrap();
- let proj = repo.identity_doc().unwrap().project().unwrap().unwrap();
- git::fmt::lit::refs_heads(proj.default_branch()).into()
+ let name = repo.default_branch_name().unwrap();
+ git::refs::branch(&name)
};
alice.commit_to(rid, &default_branch);
@@ -2186,16 +2182,27 @@ fn fetch_emits_canonical_ref_update_partial_glob() {
.unwrap()
.doc
.with_edits(|raw| {
+ // The canonical references payload is now the sole source of
+ // truth for the default branch, so it must carry the default
+ // branch rule and `HEAD` symbolic reference alongside the
+ // partial-glob rule under test.
let crefs = serde_json::json!({
"rules": {
+ "refs/heads/master": {
+ "threshold": 1,
+ "allow": "delegates"
+ },
"refs/heads/main*": {
"threshold": 1,
"allow": "delegates"
}
+ },
+ "symbolic": {
+ "HEAD": "refs/heads/master"
}
});
- raw.payload.insert(
+ raw.payload_mut().insert(
radicle::identity::doc::PayloadId::canonical_refs().clone(),
radicle::identity::doc::Payload::from(crefs),
);
diff --git a/crates/radicle-node/src/worker.rs b/crates/radicle-node/src/worker.rs
index 6aa66636c4..d262cc4945 100644
--- a/crates/radicle-node/src/worker.rs
+++ b/crates/radicle-node/src/worker.rs
@@ -125,7 +125,9 @@ impl Worker {
config,
} => {
log::debug!(target: "worker", "Worker processing outgoing fetch for {rid}");
- let result = self.fetch(rid, remote, refs_at, config, channels, notifs);
+ let result = self
+ .fetch(rid, remote, refs_at, config, channels, notifs)
+ .map(Box::new);
FetchResult::Initiator { rid, result }
}
FetchRequest::Responder { remote, emitter } => {
diff --git a/crates/radicle-protocol/src/service.rs b/crates/radicle-protocol/src/service.rs
index be4954b5e4..3ce3952b19 100644
--- a/crates/radicle-protocol/src/service.rs
+++ b/crates/radicle-protocol/src/service.rs
@@ -1052,7 +1052,7 @@ where
&mut self,
rid: RepoId,
from: NodeId,
- result: Result<crate::worker::fetch::FetchResult, crate::worker::FetchError>,
+ result: Result<Box<crate::worker::fetch::FetchResult>, crate::worker::FetchError>,
) {
let cmd = fetcher::state::command::Fetched { from, rid };
let fetcher::service::FetchCompleted { event, subscribers } = self.fetcher.fetched(cmd);
@@ -1079,7 +1079,7 @@ where
for responder in subscribers {
responder.ok(fetch_result.clone()).ok();
}
- match result {
+ match result.map(|result| *result) {
Ok(crate::worker::fetch::FetchResult {
updated,
canonical,
diff --git a/crates/radicle-protocol/src/worker.rs b/crates/radicle-protocol/src/worker.rs
index 4874d797a9..f690daf1f9 100644
--- a/crates/radicle-protocol/src/worker.rs
+++ b/crates/radicle-protocol/src/worker.rs
@@ -108,7 +108,10 @@ pub enum FetchResult {
/// Repo fetched.
rid: RepoId,
/// Fetch result, including remotes fetched.
- result: Result<fetch::FetchResult, FetchError>,
+ ///
+ /// Boxed because a successful result carries the fetched namespaces and
+ /// ref updates, which dwarf everything else this message holds.
+ result: Result<Box<fetch::FetchResult>, FetchError>,
},
Responder {
/// Repo requested.
diff --git a/crates/radicle/src/cob/identity.rs b/crates/radicle/src/cob/identity.rs
index 9afe0b7ab3..3b695d312f 100644
--- a/crates/radicle/src/cob/identity.rs
+++ b/crates/radicle/src/cob/identity.rs
@@ -1072,8 +1072,14 @@ impl Revision {
})
}
- pub fn sign(&self, signer: &impl crypto::Signer) -> Result<Signature, DocError> {
- self.doc.signature_of(signer)
+ /// Sign this revision, so a delegate can vote on it.
+ ///
+ /// The signature covers [`Revision::blob`], the document blob as stored.
+ /// Verification checks the signature against that same blob, so signing a
+ /// re-encoding of the in-memory document would break the vote whenever the
+ /// two disagreed.
+ pub fn sign(&self, signer: &impl crypto::Signer) -> Signature {
+ signer.sign(self.blob.as_ref())
}
}
@@ -1282,7 +1288,7 @@ where
}
#[allow(deprecated)]
- let signature = revision.sign(self.store.signer())?;
+ let signature = revision.sign(self.store.signer());
self.transaction("Accept revision", |tx, _| tx.accept(id, signature))
}
@@ -1397,6 +1403,66 @@ mod test {
assert_eq!(format!("\"{did}\""), json);
}
+ #[test]
+ fn migrate_version_1_identity() {
+ use crate::identity::doc::{IDENTITY_VERSION, Version};
+ use crate::storage::git::transport;
+
+ let v1 = Version::new(1).unwrap();
+ let tempdir = tempfile::tempdir().unwrap();
+ let storage = Storage::open(tempdir.path().join("storage"), fixtures::user()).unwrap();
+ transport::local::register(storage.clone());
+
+ let alice = SigningKey::mock(300);
+ let bob = SigningKey::mock(301);
+ let (working, _) = fixtures::repository(tempdir.path().join("working"));
+ let (rid, _, _) = rad::init_at(
+ v1,
+ &working,
+ "heartwood".try_into().unwrap(),
+ "Radicle Heartwood Protocol & Stack",
+ git::fmt::refname!("master"),
+ Visibility::default(),
+ &alice,
+ &storage,
+ )
+ .unwrap();
+ let repo = storage.repository(rid).unwrap();
+ let mut identity = Identity::load_mut(&repo, &alice).unwrap();
+ assert_eq!(identity.doc().version(), v1);
+
+ // Add Bob as a delegate, so that migrating needs a vote. An ordinary
+ // edit keeps the document at its stored version.
+ let mut doc = identity.doc().clone().edit();
+ doc.delegate(bob.public_key().into());
+ let r1 = identity
+ .update(Title::new("Add Bob").unwrap(), "", &doc.verified().unwrap())
+ .unwrap();
+ assert!(identity.revision(&r1).unwrap().is_accepted());
+ assert_eq!(identity.doc().version(), v1);
+
+ // The migration differs from its parent, so `DocUnchanged` does not
+ // fire, and it waits on Bob's vote.
+ let migrated = identity.doc().migrated().unwrap();
+ let r2 = identity
+ .update(Title::new("Migrate identity").unwrap(), "", &migrated)
+ .unwrap();
+ assert_eq!(identity.revision(&r2).unwrap().state, State::Active);
+ assert_eq!(identity.current, r1);
+
+ // Bob votes on a revision whose parent is a version-1 document.
+ let mut bob_identity = Identity::load_mut(&repo, &bob).unwrap();
+ bob_identity.accept(&r2).unwrap();
+ identity.reload().unwrap();
+
+ assert_eq!(identity.current, r2);
+ assert_eq!(identity.doc().version(), IDENTITY_VERSION);
+ assert_eq!(
+ identity.doc().default_branch().unwrap().as_str(),
+ "refs/heads/master"
+ );
+ }
+
#[test]
fn identity_updates() {
let NodeWithRepo { node, repo } = NodeWithRepo::default();
@@ -1416,11 +1482,6 @@ mod test {
.unwrap_err();
assert_eq!(identity.current, r0);
- // Change threshold to `2`, even though there's only one delegate. This should
- // fail as it makes the master branch immutable.
- doc.threshold = 2;
- assert!(doc.clone().verified().is_err());
-
// Let's add another delegate.
doc.delegate(bob.public_key().into());
// The update should go through now.
@@ -1432,7 +1493,7 @@ mod test {
// With two delegates now, we need two signatures for any update to go through.
// So this next update shouldn't be accepted as canonical until the second delegate
// signs it.
- doc.visibility = Visibility::private([]);
+ *doc.visibility_mut() = Visibility::private([]);
let r2 = identity
.update(title.clone(), description, &doc.clone().verified().unwrap())
.unwrap();
@@ -1482,7 +1543,7 @@ mod test {
.unwrap();
assert_eq!(identity.current, r1);
- doc.visibility = Visibility::private([]);
+ *doc.visibility_mut() = Visibility::private([]);
let r2 = identity
.update(
cob::Title::new("Make private").unwrap(),
@@ -1518,7 +1579,7 @@ mod test {
identity.reload().unwrap();
assert_eq!(identity.current, r3);
- doc.visibility = Visibility::Public;
+ *doc.visibility_mut() = Visibility::Public;
let r3 = identity
.update(
cob::Title::new("Make public").unwrap(),
@@ -1565,7 +1626,7 @@ mod test {
assert!(bob_doc.is_delegate(&bob.signer.public_key().into()));
// Alice changes the document without making Bob aware.
- alice_doc.visibility = Visibility::private([]);
+ *alice_doc.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("Change visibility").unwrap(),
@@ -1632,7 +1693,7 @@ mod test {
)
.unwrap();
- alice_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *alice_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let a2 = alice_identity
.update(
cob::Title::new("Change visibility").unwrap(),
@@ -1682,7 +1743,7 @@ mod test {
// Alice proposes A₂. Since there are 2 delegates now, it stays Active.
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A₂").unwrap(),
@@ -1696,7 +1757,7 @@ mod test {
let mut bob_identity = Identity::load_mut(&*bob.repo, &bob.signer).unwrap();
let mut bob_doc = bob_identity.doc().clone().edit();
- bob_doc.visibility = Visibility::private([alice.signer.public_key().into()]);
+ *bob_doc.visibility_mut() = Visibility::private([alice.signer.public_key().into()]);
// We use a manual transaction to force B₁ to be a child of the Active A₂,
// rather than the Accepted A₁.
@@ -1768,7 +1829,7 @@ mod test {
// Bob proposes b1.
let mut bob_identity = Identity::load_mut(&*bob.repo, &bob.signer).unwrap();
let mut bob_doc = bob_identity.doc().clone().edit();
- bob_doc.visibility = Visibility::private([]);
+ *bob_doc.visibility_mut() = Visibility::private([]);
let b1 = cob::stable::with_advanced_timestamp(|| {
bob_identity
.update(
@@ -1782,7 +1843,7 @@ mod test {
// Eve proposes e1 (a competing sibling from a different delegate).
let mut eve_identity = Identity::load_mut(&*eve.repo, &eve.signer).unwrap();
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *eve_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let e1 = cob::stable::with_advanced_timestamp(|| {
eve_identity
.update(
@@ -1821,7 +1882,7 @@ mod test {
alice_doc.delegate(bob.signer.public_key().into());
alice_doc.delegate(eve.signer.public_key().into());
- assert_eq!(alice_doc.delegates.len(), 3);
+ assert_eq!(alice_doc.delegates().len(), 3);
let a0 = alice_identity.root;
let a1 = alice_identity // Change description to change traversal order.
@@ -1833,7 +1894,7 @@ mod test {
.unwrap();
alice_doc.rescind(&eve.signer.public_key().into()).unwrap();
- assert_eq!(alice_doc.delegates.len(), 2);
+ assert_eq!(alice_doc.delegates().len(), 2);
let a2 = alice_identity
.update(
@@ -1853,7 +1914,7 @@ mod test {
let mut eve_identity = Identity::load_mut(&*eve.repo, &eve.signer).unwrap();
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *eve_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let e1 = cob::stable::with_advanced_timestamp(|| {
eve_identity
.update(
@@ -1909,7 +1970,7 @@ mod test {
)
.unwrap();
- alice_doc.visibility = Visibility::private([]);
+ *alice_doc.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("Change visibility").unwrap(),
@@ -1933,7 +1994,7 @@ mod test {
// Then she submits a new revision.
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *eve_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let e2 = eve_identity
.update(
cob::Title::new("Change visibility").unwrap(),
@@ -2010,7 +2071,7 @@ mod test {
// a0
// Bob and Alice change the document visibility. Eve is not aware.
- bob_doc.visibility = Visibility::private([]);
+ *bob_doc.visibility_mut() = Visibility::private([]);
let b1 = bob_identity
.update(
cob::Title::new("Change visibility #1").unwrap(),
@@ -2025,7 +2086,7 @@ mod test {
// In the meantime, Eve does the same thing on her side.
let mut eve_identity = Identity::load_mut(&*eve.repo, &eve.signer).unwrap();
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([]);
+ *eve_doc.visibility_mut() = Visibility::private([]);
let e1 = eve_identity
.update(
cob::Title::new("Change visibility #2").unwrap(),
@@ -2075,7 +2136,7 @@ mod test {
// Bob proposes B1 (child of A1, the current revision).
let mut bob_identity = Identity::load_mut(&*bob.repo, &bob.signer).unwrap();
let mut bob_doc = bob_identity.doc().clone().edit();
- bob_doc.visibility = Visibility::private([]);
+ *bob_doc.visibility_mut() = Visibility::private([]);
let b1 = bob_identity
.update(
cob::Title::new("B1").unwrap(),
@@ -2088,7 +2149,7 @@ mod test {
// We use a manual transaction to set B1 as the parent, since `update()`
// always uses `self.current` (= A1, because B1 hasn't been accepted).
let mut bob_doc2 = bob_doc.clone();
- bob_doc2.visibility = Visibility::private([bob.signer.public_key().into()]);
+ *bob_doc2.visibility_mut() = Visibility::private([bob.signer.public_key().into()]);
let b2 = bob_identity
.transaction("B2", |tx, repo| {
*tx = Transaction::new_revision(
@@ -2106,7 +2167,7 @@ mod test {
// Eve proposes E1 (child of A1, sibling of B1).
let mut eve_identity = Identity::load_mut(&*eve.repo, &eve.signer).unwrap();
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *eve_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let e1 = eve_identity
.update(
cob::Title::new("E1").unwrap(),
@@ -2213,7 +2274,7 @@ mod test {
assert_eq!(alice_identity.revision(&a1).unwrap().state, State::Accepted);
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A2").unwrap(),
@@ -2276,7 +2337,7 @@ mod test {
alice_identity.reload().unwrap();
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A2").unwrap(),
@@ -2294,13 +2355,16 @@ mod test {
alice.repo.fetch(bob);
alice_identity.reload().unwrap();
- assert_eq!(
- alice_identity.revision(&a2).unwrap().state,
- State::Redacted(RedactedBy::Author)
- );
+ // Nb. `a2` is redacted by Alice concurrently with Bob's acceptance. The
+ // winner of this concurrent resolution depends on the operations' OIDs,
+ // which shift whenever the document format changes; here the acceptance
+ // wins (as the diagram below shows). The terminal-state protection this
+ // test targets is exercised by `a3` and `a4` further down, and the
+ // concurrent case itself by `concurrent_redact_and_accept_converge`.
+ assert_eq!(alice_identity.revision(&a2).unwrap().state, State::Accepted);
let mut alice_doc3 = alice_identity.doc().clone().edit();
- alice_doc3.visibility = Visibility::private([alice.signer.public_key().into()]);
+ *alice_doc3.visibility_mut() = Visibility::private([alice.signer.public_key().into()]);
let a3 = alice_identity
.update(
cob::Title::new("A3").unwrap(),
@@ -2321,7 +2385,7 @@ mod test {
assert_eq!(alice_identity.revision(&a3).unwrap().state, State::Accepted);
let mut alice_doc4 = alice_identity.doc().clone().edit();
- alice_doc4.visibility = Visibility::private([]);
+ *alice_doc4.visibility_mut() = Visibility::private([]);
let a4 = alice_identity
.update(
cob::Title::new("A4").unwrap(),
@@ -2344,9 +2408,9 @@ mod test {
// a4 (Propose "A4") 1/2 (Rejected by Bob) -> Redact attempt ignored
// |
// a3 (Propose "A3") 2/2 (Accepted by Alice, Bob) -> Redact attempt ignored
- // | \
- // | a2 (Propose "A2") 1/2 (Redacted by Alice concurrently with Bob's Accept)
- // | /
+ // |
+ // a2 (Propose "A2") 2/2 (Accepted by Bob, winning over Alice's concurrent Redact)
+ // |
// a1 (Add Bob) 2/2 (Accepted by Alice, Bob)
// |
// a0
@@ -2391,7 +2455,7 @@ mod test {
// A₂ is proposed and accepted, is acceptedy by Bob, thus reaches 2/2 votes,
// is accepted, and becomes the current revision, superseding A₁.
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A₂").unwrap(),
@@ -2446,7 +2510,7 @@ mod test {
// Alice proposes A₂. With 2 delegates, needs 2/2 votes. Stays Active.
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A₂").unwrap(),
@@ -2527,7 +2591,7 @@ mod test {
.unwrap();
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([]);
+ *alice_doc2.visibility_mut() = Visibility::private([]);
let a2 = alice_identity
.update(
cob::Title::new("A₂").unwrap(),
@@ -2595,8 +2659,8 @@ mod test {
// Make a change to the description and sign it.
let desc = prj.description().to_owned() + "!";
- let prj = prj.update(None, desc, None).unwrap();
- doc.payload
+ let prj = prj.update(None, desc).unwrap();
+ doc.payload_mut()
.insert(PayloadId::project().clone(), prj.clone().into());
identity
.update(
@@ -2608,7 +2672,6 @@ mod test {
// Add Bob as a delegate, and sign it.
doc.delegate(bob.public_key().into());
- doc.threshold = 2;
identity
.update(
cob::Title::new("Add bob").unwrap(),
@@ -2634,8 +2697,9 @@ mod test {
// Update description again with signatures by Eve and Bob.
let desc = prj.description().to_owned() + "?";
- let prj = prj.update(None, desc, None).unwrap();
- doc.payload.insert(PayloadId::project().clone(), prj.into());
+ let prj = prj.update(None, desc).unwrap();
+ doc.payload_mut()
+ .insert(PayloadId::project().clone(), prj.into());
let revision = bob_identity
.update(
cob::Title::new("Update description again").unwrap(),
@@ -2703,7 +2767,7 @@ mod test {
// Alice proposes A1 and B1
let mut doc_a1 = alice_identity.doc().clone().edit();
- doc_a1.visibility = Visibility::private([]);
+ *doc_a1.visibility_mut() = Visibility::private([]);
let a1 = alice_identity
.update(
cob::Title::new("A1").unwrap(),
@@ -2713,7 +2777,7 @@ mod test {
.unwrap();
let mut doc_b1 = doc_a1.clone();
- doc_b1.visibility = Visibility::private([bob.signer.public_key().into()]);
+ *doc_b1.visibility_mut() = Visibility::private([bob.signer.public_key().into()]);
let b1 = alice_identity
.transaction("B1", |tx, repo| {
*tx = Transaction::new_revision(
@@ -2822,7 +2886,7 @@ mod test {
// B1: Alice proposes a child of A2 (changes visibility).
// B1's parent is A2 (Active, not current), so we use a manual transaction.
let mut doc_b1 = doc_a2.clone();
- doc_b1.visibility = Visibility::private([]);
+ *doc_b1.visibility_mut() = Visibility::private([]);
let b1 = alice_identity
.transaction("B1", |tx, repo| {
*tx = Transaction::new_revision(
@@ -2930,7 +2994,7 @@ mod test {
// Note that at this point, A₁ is still the currently accepted revision,
// meaning Dave is a delegate according to the currently accepted revision.
let mut doc_a3 = doc_a2.clone();
- doc_a3.visibility = Visibility::private([]);
+ *doc_a3.visibility_mut() = Visibility::private([]);
let a3 = alice_identity
.transaction("A₃", |tx, repo| {
*tx = Transaction::new_revision(
@@ -2989,7 +3053,7 @@ mod test {
// Alice proposes a revision (child of current). Alice has an implicit accept.
let mut doc1 = alice_identity.doc().clone().edit();
- doc1.visibility = Visibility::private([]);
+ *doc1.visibility_mut() = Visibility::private([]);
let child = alice_identity
.update(
cob::Title::new("Child 1").unwrap(),
@@ -3035,7 +3099,7 @@ mod test {
bob.repo.fetch(alice);
let mut bob_identity = Identity::load_mut(&*bob.repo, &bob.signer).unwrap();
let mut bob_doc = bob_identity.doc().clone().edit();
- bob_doc.visibility = Visibility::private([]);
+ *bob_doc.visibility_mut() = Visibility::private([]);
let child_a = bob_identity
.update(
cob::Title::new("Child A").unwrap(),
@@ -3046,7 +3110,7 @@ mod test {
// Alice proposes child_b (sibling, gets implicit accept).
let mut alice_doc2 = alice_identity.doc().clone().edit();
- alice_doc2.visibility = Visibility::private([alice.signer.public_key().into()]);
+ *alice_doc2.visibility_mut() = Visibility::private([alice.signer.public_key().into()]);
let _child_b = alice_identity
.update(
cob::Title::new("Child B").unwrap(),
@@ -3064,8 +3128,7 @@ mod test {
let sig = alice_identity
.revision(&child_a)
.unwrap()
- .sign(&alice.signer)
- .unwrap();
+ .sign(&alice.signer);
alice_identity
.transaction("Accept child_a", |tx, _| tx.accept(child_a, sig))
.unwrap();
@@ -3105,7 +3168,7 @@ mod test {
// Alice proposes first child (gets implicit accept).
let mut doc1 = alice_identity.doc().clone().edit();
- doc1.visibility = Visibility::private([]);
+ *doc1.visibility_mut() = Visibility::private([]);
let child1 = alice_identity
.update(
cob::Title::new("Child 1").unwrap(),
@@ -3116,7 +3179,7 @@ mod test {
// Alice proposes second child via transaction (simulating old history).
let mut doc2 = doc1.clone();
- doc2.visibility = Visibility::private([alice.signer.public_key().into()]);
+ *doc2.visibility_mut() = Visibility::private([alice.signer.public_key().into()]);
let current = alice_identity.current;
let child2 = alice_identity
.transaction("Child 2", |tx, repo| {
@@ -3188,7 +3251,7 @@ mod test {
bob.repo.fetch(alice);
let mut bob_identity = Identity::load_mut(&*bob.repo, &bob.signer).unwrap();
let mut bob_doc = bob_identity.doc().clone().edit();
- bob_doc.visibility = Visibility::private([]);
+ *bob_doc.visibility_mut() = Visibility::private([]);
let child_a = bob_identity
.update(
cob::Title::new("Child A").unwrap(),
@@ -3201,7 +3264,7 @@ mod test {
eve.repo.fetch(alice);
let mut eve_identity = Identity::load_mut(&*eve.repo, &eve.signer).unwrap();
let mut eve_doc = eve_identity.doc().clone().edit();
- eve_doc.visibility = Visibility::private([eve.signer.public_key().into()]);
+ *eve_doc.visibility_mut() = Visibility::private([eve.signer.public_key().into()]);
let child_b = eve_identity
.update(
cob::Title::new("Child B").unwrap(),
@@ -3252,7 +3315,7 @@ mod test {
// Alice proposes first child.
let mut doc1 = alice_identity.doc().clone().edit();
- doc1.visibility = Visibility::private([]);
+ *doc1.visibility_mut() = Visibility::private([]);
let _child1 = alice_identity
.update(
cob::Title::new("Child 1").unwrap(),
@@ -3263,7 +3326,7 @@ mod test {
// Alice tries to propose a second child (sibling) — should fail.
let mut doc2 = alice_identity.doc().clone().edit();
- doc2.visibility = Visibility::private([alice.signer.public_key().into()]);
+ *doc2.visibility_mut() = Visibility::private([alice.signer.public_key().into()]);
let err = alice_identity
.update(
cob::Title::new("Child 2").unwrap(),
diff --git a/crates/radicle/src/cob/identity/test/property.rs b/crates/radicle/src/cob/identity/test/property.rs
index 1036845af3..1822c278cb 100644
--- a/crates/radicle/src/cob/identity/test/property.rs
+++ b/crates/radicle/src/cob/identity/test/property.rs
@@ -139,7 +139,6 @@ impl Harness {
let mut alice_doc = alice_identity.doc().clone().edit();
alice_doc.delegate(bob.signer.public_key().into());
alice_doc.delegate(eve.signer.public_key().into());
- alice_doc.threshold = 2;
let a1 = alice_identity
.update(
@@ -433,8 +432,9 @@ impl Harness {
fn update_description(&self, doc: &mut crate::prelude::RawDoc, msg: &str) {
let prj = doc.project().unwrap().unwrap();
let desc = format!("{} {}", msg, self.revisions.len());
- let prj = prj.update(None, desc, None).unwrap();
- doc.payload.insert(PayloadId::project().clone(), prj.into());
+ let prj = prj.update(None, desc).unwrap();
+ doc.payload_mut()
+ .insert(PayloadId::project().clone(), prj.into());
}
fn did_for(&self, actor: &Actor) -> Did {
@@ -449,14 +449,9 @@ impl Harness {
fn toggle_delegate(&self, delegate: &Actor, doc: &mut crate::prelude::RawDoc) {
let target_delegate: Did = self.did_for(delegate);
- if doc.delegates.contains(&target_delegate) {
- if doc.delegates.len() > 1 {
+ if doc.delegates().contains(&target_delegate) {
+ if doc.delegates().len() > 1 {
doc.rescind(&target_delegate).unwrap();
-
- // Ensure threshold never exceeds new delegate count
- if doc.threshold > doc.delegates.len() {
- doc.threshold = doc.delegates.len();
- }
}
} else {
doc.delegate(target_delegate);
diff --git a/crates/radicle/src/cob/patch.rs b/crates/radicle/src/cob/patch.rs
index 8016b63927..2c3eaf0c3a 100644
--- a/crates/radicle/src/cob/patch.rs
+++ b/crates/radicle/src/cob/patch.rs
@@ -3042,7 +3042,6 @@ mod test {
use crate::cob::common::CodeRange;
use crate::cob::test::SignerOpExt as _;
use crate::crypto::{Signer as _, SigningKey};
- use crate::git::BranchName;
use crate::identity;
use crate::identity::doc::RawDoc;
use crate::identity::project::{Project, ProjectName};
@@ -3138,12 +3137,12 @@ mod test {
let project = Project::new(
ProjectName::from_str("test_merge_target_resolution").unwrap(),
String::from(""),
- BranchName::from(git::fmt::RefString::try_from("master").unwrap()),
);
let doc = RawDoc::new(
project.unwrap(),
vec![alice.did()],
+ &git::fmt::refname!("master"),
1,
identity::Visibility::Public,
)
@@ -3196,22 +3195,22 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
+ &git::fmt::refname!("master"),
1,
identity::Visibility::Public,
);
- let rules = serde_json::json!({
- "refs/heads/accepted": {
- "allow": "delegates",
- "threshold": 1
- },
- "refs/tags/v1.0": {
- "allow": "delegates",
- "threshold": 1
+ // Keep a valid default branch (`master`) while adding the custom rules
+ // this test exercises, so the document verifies.
+ let crefs = serde_json::json!({
+ "symbolic": { "HEAD": "refs/heads/master" },
+ "rules": {
+ "refs/heads/master": { "allow": "delegates", "threshold": 1 },
+ "refs/heads/accepted": { "allow": "delegates", "threshold": 1 },
+ "refs/tags/v1.0": { "allow": "delegates", "threshold": 1 }
}
});
- let crefs = serde_json::json!({ "rules": rules });
- raw_doc.payload.insert(
+ raw_doc.payload_mut().insert(
identity::doc::PayloadId::canonical_refs().clone(),
identity::doc::Payload::from(crefs),
);
@@ -3280,20 +3279,21 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![bob.did()],
+ &git::fmt::refname!("master"),
1,
identity::Visibility::Public,
);
- let rules = serde_json::json!({
- "refs/heads/accepted": {
- "allow": [alice.did()],
- "threshold": 1
- }
- });
+ // Keep a valid default branch (`master`) while adding the custom rule
+ // (governed by a non-delegate `allow` set) this test exercises.
let crefs = serde_json::json!({
- "rules": rules
+ "symbolic": { "HEAD": "refs/heads/master" },
+ "rules": {
+ "refs/heads/master": { "allow": "delegates", "threshold": 1 },
+ "refs/heads/accepted": { "allow": [alice.did()], "threshold": 1 }
+ }
});
- raw_doc.payload.insert(
+ raw_doc.payload_mut().insert(
identity::doc::PayloadId::canonical_refs().clone(),
identity::doc::Payload::from(crefs),
);
@@ -3339,20 +3339,21 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
+ &git::fmt::refname!("master"),
1,
identity::Visibility::Public,
);
- let rules = serde_json::json!({
- "refs/heads/accepted": {
- "allow": [alice.did()],
- "threshold": 1
- }
- });
+ // Keep a valid default branch (`master`) while adding the custom rule
+ // (governed by a non-delegate `allow` set) this test exercises.
let crefs = serde_json::json!({
- "rules": rules
+ "symbolic": { "HEAD": "refs/heads/master" },
+ "rules": {
+ "refs/heads/master": { "allow": "delegates", "threshold": 1 },
+ "refs/heads/accepted": { "allow": [alice.did()], "threshold": 1 }
+ }
});
- raw_doc.payload.insert(
+ raw_doc.payload_mut().insert(
identity::doc::PayloadId::canonical_refs().clone(),
identity::doc::Payload::from(crefs),
);
@@ -3393,7 +3394,7 @@ mod test {
///
/// The document has four delegates and a threshold of three, while the
/// rule matching the target branch allows only Alice and Bob, with a
- /// threshold of two. The two quorums are distinguishable.
+ /// threshold of two. The two quorums are therefore distinguishable.
fn merge_quorum_fixture(
signers: &[&SigningKey],
commit: git::Oid,
@@ -3406,18 +3407,26 @@ mod test {
let mut raw_doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did(), bob.did(), eve.did(), dave.did()],
+ &git::fmt::refname!("master"),
3,
identity::Visibility::Public,
);
+ // Keep a valid default branch (`master`) alongside the rule this test
+ // exercises, so the document verifies.
let crefs = serde_json::json!({
+ "symbolic": { "HEAD": "refs/heads/master" },
"rules": {
+ "refs/heads/master": {
+ "allow": "delegates",
+ "threshold": 3
+ },
"refs/heads/accepted": {
"allow": [alice.did(), bob.did()],
"threshold": 2
}
}
});
- raw_doc.payload.insert(
+ raw_doc.payload_mut().insert(
identity::doc::PayloadId::canonical_refs().clone(),
identity::doc::Payload::from(crefs),
);
@@ -3479,7 +3488,7 @@ mod test {
}
#[test]
- fn test_patch_merge_quorum_uses_rule_threshold() {
+ fn patch_merge_quorum_uses_rule_threshold() {
let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
let bob = SigningKey::mock(23);
@@ -3506,7 +3515,7 @@ mod test {
}
#[test]
- fn test_patch_merge_quorum_ignores_disallowed_merges() {
+ fn patch_merge_quorum_ignores_disallowed_merges() {
let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
let bob = SigningKey::mock(23);
@@ -3530,22 +3539,24 @@ mod test {
}
#[test]
- fn test_patch_merge_quorum_without_matching_rule() {
+ fn patch_merge_quorum_without_matching_rule() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
- // The only rule is the one synthesized for the default branch, so
- // nothing matches `refs/heads/staging`.
- let project = Project::new(
- ProjectName::from_str("unruled").unwrap(),
- String::new(),
- BranchName::from(git::fmt::RefString::try_from("master").unwrap()),
+ // The only rule is the one written for the default branch, so nothing
+ // matches `refs/heads/staging`.
+ let project =
+ Project::new(ProjectName::from_str("unruled").unwrap(), String::new()).unwrap();
+ let doc = RawDoc::new(
+ project,
+ vec![alice.did()],
+ &git::fmt::refname!("master"),
+ 1,
+ identity::Visibility::Public,
)
+ .verified()
.unwrap();
- let doc = RawDoc::new(project, vec![alice.did()], 1, identity::Visibility::Public)
- .verified()
- .unwrap();
let branch = git::fmt::qualified!("refs/heads/staging");
let mut repo = MockRepository::new(r#gen::<RepoId>(1), doc.clone());
@@ -3587,26 +3598,23 @@ mod test {
/// The default branch keeps the quorum it had before rules were consulted.
///
- /// Without a `xyz.radicle.crefs` payload, the rule for the default branch
- /// is synthesized as `delegates` at the document threshold, so the tally
- /// must behave exactly as it did when it used the document directly.
+ /// `RawDoc::new` writes the rule for the default branch as `delegates` at
+ /// the given threshold, so the tally must behave exactly as it did when it
+ /// used the document threshold directly.
#[test]
- fn test_patch_merge_quorum_of_default_branch() {
+ fn patch_merge_quorum_of_default_branch() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
let bob = SigningKey::mock(23);
let eve = SigningKey::mock(31);
- let project = Project::new(
- ProjectName::from_str("unruled").unwrap(),
- String::new(),
- BranchName::from(git::fmt::RefString::try_from("master").unwrap()),
- )
- .unwrap();
+ let project =
+ Project::new(ProjectName::from_str("unruled").unwrap(), String::new()).unwrap();
let doc = RawDoc::new(
project,
vec![alice.did(), bob.did(), eve.did()],
+ &git::fmt::refname!("master"),
2,
identity::Visibility::Public,
)
@@ -3645,14 +3653,14 @@ mod test {
apply_merge(&mut patch, &doc, &repo, revision, commit, &alice);
assert!(
!patch.is_merged(),
- "one of three delegates is below the document threshold"
+ "one of three delegates is below the rule's threshold"
);
apply_merge(&mut patch, &doc, &repo, revision, commit, &bob);
assert_eq!(
*patch.state(),
State::Merged { revision, commit },
- "the synthesized rule resolves to the document threshold of two"
+ "the default branch rule resolves to its threshold of two"
);
}
@@ -3901,6 +3909,7 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
vec![alice.did()],
+ &git::fmt::refname!("master"),
1,
identity::Visibility::Public,
)
diff --git a/crates/radicle/src/identity/crefs.rs b/crates/radicle/src/identity/crefs.rs
index daced4cf66..c79ebca8d2 100644
--- a/crates/radicle/src/identity/crefs.rs
+++ b/crates/radicle/src/identity/crefs.rs
@@ -33,7 +33,7 @@ pub enum ValidationError {
/// Configuration for canonical references and their rules.
///
/// [`RawCanonicalRefs`] are verified into [`CanonicalRefs`].
-#[derive(Default, Debug, Clone, PartialEq, Eq, Deserialize)]
+#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RawCanonicalRefs {
rules: RawRules,
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index 756a7a36e5..b9b3f2e04e 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -1,9 +1,15 @@
+pub mod migrate;
+pub mod raw;
pub mod update;
+pub mod v1;
+pub mod v2;
+
+pub use raw::RawDoc;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
use std::num::{NonZeroU32, NonZeroUsize};
-use std::ops::{Deref, Not};
+use std::ops::Deref;
use std::path::Path;
use std::str::FromStr;
use std::sync::LazyLock;
@@ -19,8 +25,6 @@ use crate::cob::identity;
use crate::crypto;
use crate::crypto::Signature;
use crate::git;
-use crate::git::canonical::rules::{self, ResolvedDelegates};
-use crate::git::fmt::Qualified;
use crate::git::fmt::RefString;
use crate::git::raw::ErrorExt as _;
use crate::identity::crefs;
@@ -41,8 +45,17 @@ pub const MAX_STRING_LENGTH: usize = 255;
/// Maximum number of a delegates in the identity document.
pub const MAX_DELEGATES: usize = 255;
/// The current, most recent version of the identity document.
+///
+/// Version 2 replaced the top-level `threshold` and the project's
+/// `defaultBranch` with the `xyz.radicle.crefs` payload (see [`canonical`]),
+/// which governs the default branch and its write quorum. Version 1 documents
+/// stay readable: they are migrated in memory when they are loaded (see
+/// [`migrate`]), and `rad id migrate` proposes the migration as a revision that
+/// the delegates vote on.
+///
+/// [`canonical`]: crate::git::canonical
// SAFETY: identity version should never be 0, so we can use `unsafe` here
-pub const IDENTITY_VERSION: Version = Version(NonZeroU32::new(1).unwrap());
+pub const IDENTITY_VERSION: Version = Version(NonZeroU32::new(2).unwrap());
#[derive(Error, Debug)]
pub enum DocError {
@@ -54,8 +67,14 @@ pub enum DocError {
Threshold(#[from] ThresholdError),
#[error("git: {0}")]
Git(#[from] git::raw::Error),
+ #[error("could not migrate identity document: {0}")]
+ Migrate(#[from] migrate::Error),
+ #[error(transparent)]
+ DefaultBranchDisallowed(#[from] v2::DefaultBranchDisallowed),
#[error("missing identity document")]
Missing,
+ #[error("invalid default branch: {0}")]
+ DefaultBranch(#[from] DefaultBranchError),
}
#[derive(Debug, Error)]
@@ -78,14 +97,6 @@ impl DocError {
#[derive(Debug, Error)]
pub enum DefaultBranchError {
- #[error(
- "could not find default branch in any of the payloads `xyz.radicle.project` ({project}) or `xyz.radicle.crefs` ({crefs})"
- )]
- Payload {
- project: PayloadError,
- crefs: PayloadError,
- },
-
#[error("no symbolic reference with name `HEAD` is defined")]
MissingHead,
@@ -127,16 +138,24 @@ impl Version {
pub fn is_valid_version(v: &u32) -> bool {
0 < *v && *v <= IDENTITY_VERSION.into()
}
+}
- /// Helper for skipping the serialization of the version if `version <= 1`.
- ///
- /// Note that we shouldn't allow `version: 0`, but there is no harm in
- /// skipping it anyway.
- fn skip_serializing(&self) -> bool {
- u32::from(*self) <= 1
+impl FromStr for Version {
+ type Err = ParseVersionError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ Version::new(s.parse::<u32>()?).map_err(ParseVersionError::Version)
}
}
+#[derive(Debug, Error)]
+pub enum ParseVersionError {
+ #[error("`{0}` is not a version number")]
+ Number(#[from] std::num::ParseIntError),
+ #[error(transparent)]
+ Version(VersionError),
+}
+
impl From<Version> for NonZeroU32 {
fn from(Version(n): Version) -> Self {
n
@@ -312,12 +331,18 @@ pub trait GetPayload {
}
impl GetPayload for Doc {
+ fn get_payload(&self, id: &PayloadId) -> Option<&Payload> {
+ self.view.payload.get(id)
+ }
+}
+
+impl GetPayload for v1::Doc {
fn get_payload(&self, id: &PayloadId) -> Option<&Payload> {
self.payload.get(id)
}
}
-impl GetPayload for RawDoc {
+impl GetPayload for v2::Doc {
fn get_payload(&self, id: &PayloadId) -> Option<&Payload> {
self.payload.get(id)
}
@@ -403,122 +428,6 @@ impl Visibility {
}
}
-/// `RawDoc` is similar to the [`Doc`] type, however, it can be edited and may
-/// not be valid.
-///
-/// It is expected that any changes to a [`Doc`] are made via [`RawDoc`], and
-/// then verified by using [`RawDoc::verified`].
-///
-/// Note that `RawDoc` only implements [`Deserialize`]. This prevents us from
-/// serializing an unverified document, while also making sure that any document
-/// that is deserialized is verified.
-#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RawDoc {
- /// Version of the identity document.
- #[serde(default = "missing_version")]
- version: Version,
- /// The payload section.
- pub payload: BTreeMap<PayloadId, Payload>,
- /// The delegates section.
- pub delegates: Vec<Did>,
- /// The signature threshold.
- pub threshold: usize,
- /// Repository visibility.
- #[serde(default)]
- pub visibility: Visibility,
-}
-
-impl TryFrom<RawDoc> for Doc {
- type Error = DocError;
-
- fn try_from(doc: RawDoc) -> Result<Self, Self::Error> {
- doc.verified()
- }
-}
-
-impl RawDoc {
- /// Construct a new [`RawDoc`] with an initial [`RawDoc::payload`]
- /// containing the provided [`Project`], and the given `delegates`,
- /// `threshold`, and `visibility`.
- pub fn new(
- project: Project,
- delegates: Vec<Did>,
- threshold: usize,
- visibility: Visibility,
- ) -> Self {
- let project =
- serde_json::to_value(project).expect("Doc::initial: payload must be serializable");
-
- Self {
- version: IDENTITY_VERSION,
- payload: BTreeMap::from_iter([(PayloadId::project().clone(), Payload::from(project))]),
- delegates,
- threshold,
- visibility,
- }
- }
-
- /// Get the version of the document.
- pub fn version(&self) -> &Version {
- &self.version
- }
-
- /// Check if the given `did` is in the set of [`RawDoc::delegates`].
- pub fn is_delegate(&self, did: &Did) -> bool {
- self.delegates.contains(did)
- }
-
- /// Add a new delegate to the document.
- ///
- /// Note that if this `Did` is a duplicate, then the resulting set will only
- /// show it once.
- pub fn delegate(&mut self, did: Did) {
- self.delegates.push(did)
- }
-
- /// Remove the `did` from the set of delegates. Returns `true` if it was
- /// removed.
- pub fn rescind(&mut self, did: &Did) -> Result<bool, DocError> {
- let (matches, delegates) = self.delegates.iter().partition(|d| *d == did);
- self.delegates = delegates;
- Ok(matches.is_empty().not())
- }
-
- /// Construct the `RawDoc` from the set of `bytes` that are expected to be
- /// in JSON format.
- pub fn from_json(bytes: &[u8]) -> Result<Self, DocError> {
- serde_json::from_slice(bytes).map_err(DocError::from)
- }
-
- /// Verify the `RawDoc`'s values, converting it into a valid [`Doc`].
- ///
- /// The verifications are as follows:
- ///
- /// - [`RawDoc::delegates`]: any duplicates are removed, and for the
- /// remaining set ensure that it is non-empty and does not exceed a
- /// length of [`MAX_DELEGATES`].
- /// - [`RawDoc::threshold`]: ensure that it is in the range `[1, delegates.len()]`.
- pub fn verified(self) -> Result<Doc, DocError> {
- let RawDoc {
- version,
- payload,
- delegates,
- threshold,
- visibility,
- } = self;
- let delegates = Delegates::new(delegates)?;
- let threshold = Threshold::new(threshold, &delegates)?;
- Ok(Doc {
- version,
- payload,
- delegates,
- threshold,
- visibility,
- })
- }
-}
-
/// A valid set of delegates for the identity [`Doc`].
///
/// It can only be constructed via [`Delegates::new`].
@@ -687,36 +596,91 @@ impl Threshold {
/// [`RawDoc`] and use [`RawDoc::verified`] to construct the `Doc`.
/// 4. [`Doc::from_blob`]: construct a `Doc` from a Git blob by deserializing
/// its contents.
-#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
+///
+/// The document is held twice, in two roles that must not be confused:
+///
+/// - The **stored** form, [`Doc::raw`], decides the document's identity. The
+/// [`RepoId`] is the Git blob id of the canonically-encoded root document,
+/// and every revision signature covers a blob id. It is also what a
+/// delegate edits. Serializing a `Doc` writes this form, so serializing a
+/// version-1 document yields version-1 JSON.
+/// - The **migrated** form, the view, is what every reader consumes. Holding
+/// it materialized keeps version conditionals out of reader code.
+#[derive(Debug, Clone, Eq, Deserialize)]
#[serde(try_from = "RawDoc")]
pub struct Doc {
- #[serde(skip_serializing_if = "Version::skip_serializing")]
- version: Version,
- payload: BTreeMap<PayloadId, Payload>,
+ /// The document as stored. Decides identity, serialization and signing.
+ raw: RawDoc,
+ /// The document migrated to [`IDENTITY_VERSION`]. Every read goes through
+ /// this.
+ view: v2::Doc,
+ /// The delegates, validated. They are the same in `raw` and in `view`,
+ /// since migration never touches them.
delegates: Delegates,
- threshold: Threshold,
- #[serde(default, skip_serializing_if = "Visibility::is_public")]
- visibility: Visibility,
+}
+
+impl PartialEq for Doc {
+ /// Two documents are equal when they are stored identically.
+ ///
+ /// The view is a function of the stored form, so comparing the stored form
+ /// alone loses nothing. It also states the intent: two documents that
+ /// migrate to the same view but differ on disk are different documents,
+ /// which is what lets a migration revision differ from its parent and so
+ /// pass the `DocUnchanged` check.
+ fn eq(&self, other: &Self) -> bool {
+ self.raw == other.raw
+ }
+}
+
+impl Serialize for Doc {
+ fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ self.raw.serialize(serializer)
+ }
}
impl Doc {
- /// Construct the initial [`Doc`] for an identity.
+ /// Construct the initial [`Doc`] for an identity at [`IDENTITY_VERSION`].
///
- /// It will begin with the provided `project` in the [`Doc::payload`], the
- /// `delegate` as the sole delegate, a threshold of 1, and the given
- /// `visibility`.
- pub fn initial(project: Project, delegate: Did, visibility: Visibility) -> Self {
- let project =
- serde_json::to_value(project).expect("Doc::initial: payload must be serializable");
-
- Self {
- version: IDENTITY_VERSION,
- payload: BTreeMap::from_iter([(PayloadId::project().clone(), Payload::from(project))]),
- delegates: Delegates(NonEmpty::new(delegate)),
- threshold: Threshold(NonZeroUsize::MIN),
+ /// It will begin with the provided `project` in the [`Doc::payload`], a
+ /// `xyz.radicle.crefs` payload governing `default_branch` with a threshold
+ /// of 1, the `delegate` as the sole delegate, and the given `visibility`.
+ pub fn initial(
+ project: Project,
+ delegate: Did,
+ default_branch: &RefString,
+ visibility: Visibility,
+ ) -> Self {
+ Self::initial_at(
+ IDENTITY_VERSION,
+ project,
+ delegate,
+ default_branch,
visibility,
- }
+ )
+ .expect("Doc::initial: initial document must be valid")
+ }
+
+ /// Like [`Doc::initial`], but at the given document `version`.
+ ///
+ /// Initializing at an older version is deliberate: the repository stays
+ /// readable to releases that predate [`IDENTITY_VERSION`], until
+ /// `rad id migrate` is run.
+ pub fn initial_at(
+ version: Version,
+ project: Project,
+ delegate: Did,
+ default_branch: &RefString,
+ visibility: Visibility,
+ ) -> Result<Self, DocError> {
+ RawDoc::new_at(
+ version,
+ project,
+ vec![delegate],
+ default_branch,
+ 1,
+ visibility,
+ )
+ .verified()
}
/// Construct a [`Doc`] contained in the provided Git blob.
@@ -726,21 +690,29 @@ impl Doc {
/// Convert the [`Doc`] into a [`RawDoc`] for changing the field values and
/// re-verifying.
+ ///
+ /// The edited document keeps its stored version, so an ordinary edit of a
+ /// version-1 document proposes another version-1 document.
pub fn edit(self) -> RawDoc {
- let Doc {
- version,
- payload,
- delegates,
- threshold,
- visibility,
- } = self;
- RawDoc {
- version,
- payload,
- delegates: delegates.into(),
- threshold: threshold.into(),
- visibility,
- }
+ self.raw
+ }
+
+ /// The document as stored.
+ ///
+ /// Use this where the stored form is what matters — showing a delegate what
+ /// they are about to edit, or diffing two revisions — rather than the
+ /// migrated view that [`Doc::payload`] and friends return.
+ pub fn raw(&self) -> &RawDoc {
+ &self.raw
+ }
+
+ /// The document migrated to [`IDENTITY_VERSION`], which is what
+ /// `rad id migrate` proposes as a new revision.
+ ///
+ /// For a document that is already at [`IDENTITY_VERSION`] this is the
+ /// document itself, so proposing it would be a no-op.
+ pub fn migrated(&self) -> Result<Doc, DocError> {
+ RawDoc::V2(self.view.clone()).verified()
}
/// Using the current state of the `Doc`, perform any edits on the `RawDoc`
@@ -754,14 +726,14 @@ impl Doc {
raw.verified()
}
- /// Get the version of the document.
- pub fn version(&self) -> &Version {
- &self.version
+ /// Get the version of the document, as stored.
+ pub fn version(&self) -> Version {
+ self.raw.version()
}
/// Return the associated payloads for this [`Doc`].
pub fn payload(&self) -> &BTreeMap<PayloadId, Payload> {
- &self.payload
+ &self.view.payload
}
/// Gets the qualified reference name of the default branch,
@@ -776,176 +748,49 @@ impl Doc {
Ok(qualified.to_owned())
}
- pub fn default_branch_name(&self) -> Result<git::fmt::RefString, DefaultBranchError> {
+ /// Gets the short name of the default branch, i.e. the target of the `HEAD`
+ /// symbolic reference with the `refs/heads/` prefix removed.
+ pub fn default_branch_name(&self) -> Result<RefString, DefaultBranchError> {
let qualified = self.default_branch()?;
- Ok(qualified
- .strip_prefix(RefString::try_from("refs/heads").expect("valid refstring"))
- .expect("valid branch")
- .to_ref_string())
+ let name = qualified
+ .as_str()
+ .strip_prefix("refs/heads/")
+ .and_then(|name| RefString::try_from(name).ok())
+ .ok_or(DefaultBranchError::MissingHead)?;
+ Ok(name)
}
/// Construct the canonical references for this document.
///
- /// Uses the `xyz.radicle.crefs` payload (if present) and the
- /// `xyz.radicle.project` payload to determine the `HEAD` symbolic
- /// reference and its associated rule.
- ///
- /// There are three cases, depending on whether `HEAD` is already
- /// defined in the crefs payload and whether a project payload exists:
- ///
- /// 1. **Explicit HEAD + project**: `HEAD` must agree with
- /// [`Project::default_branch_qualified`], and the matching rule must
- /// use `delegates` with the document's threshold.
- /// 2. **Explicit HEAD, no project**: The matching rule must use
- /// `delegates` with the document's threshold.
- /// 3. **No HEAD**: A rule and `HEAD` symbolic reference are synthesized
- /// from the project payload (which must exist).
- ///
- /// In all cases the result must pass [`RawCanonicalRefs::try_into_canonical_refs`]
- /// validation. If a rule for `HEAD`'s target is missing, it will be
- /// caught as a dangling reference there.
+ /// The canonical references, including the default branch and its `HEAD`
+ /// symbolic reference, are governed entirely by the `xyz.radicle.crefs`
+ /// payload. The payload must be present and must pass
+ /// [`RawCanonicalRefs::try_into_canonical_refs`] validation.
///
/// [`RawCanonicalRefs`]: super::crefs::RawCanonicalRefs
pub fn canonical_refs(&self) -> Result<CanonicalRefs, CanonicalRefsError> {
- let resolve = &mut || self.delegates.clone();
- let crefs = self
+ let raw_crefs = self
.raw_canonical_refs()
- .transpose()
- .map_err(CanonicalRefsError::Payload)?
- .map(|crefs| crefs.try_into_canonical_refs(resolve))
- .transpose()
- .map_err(CanonicalRefsError::CanonicalRefs)?
- .unwrap_or_default();
-
- // Determine where `HEAD` comes from. The `resolve_head()` result
- // borrows `raw_crefs`, so clone to allow mutation in the synthesis
- // path.
- let head: Option<Qualified<'static>> = crefs.symbolic().resolve_head().cloned();
-
- match (head, self.project()) {
- (Some(ref default_branch), Some(Ok(project))) => {
- let project_branch = project.default_branch_qualified();
- if project_branch != *default_branch {
- return Err(CanonicalRefsError::DefaultBranchRuleError(
- DefaultBranchRuleError::HeadMismatch {
- cref: default_branch.to_ref_string(),
- project: project_branch.to_ref_string(),
- },
- ));
- }
- self.validate_head_rule(&crefs, default_branch)?;
- }
- (Some(ref default_branch), None) => {
- self.validate_head_rule(&crefs, default_branch)?;
- }
- (None, Some(Ok(project))) => {
- return Ok(self
- .synthesize_head(crefs, &project)
- .try_into_canonical_refs(resolve)?);
- }
- (None, None) => {
- return Err(CanonicalRefsError::SynthesisPayloadMissing);
- }
- (_, Some(Err(err))) => {
- return Err(CanonicalRefsError::ProjectPayload(err));
- }
- }
-
- Ok(crefs)
- }
-
- /// Validate that the rule matching `HEAD`'s target branch uses
- /// `delegates` and the document's threshold.
- ///
- /// If no rule matches the target, `HEAD` will dangle — this is caught
- /// later by [`RawCanonicalRefs::try_into_canonical_refs`] validation.
- fn validate_head_rule(
- &self,
- crefs: &CanonicalRefs,
- default_branch: &Qualified<'static>,
- ) -> Result<(), CanonicalRefsError> {
- let Some((pattern, rule)) = crefs.rules().matches(default_branch).next() else {
- return Ok(());
- };
-
- let _allowed = rule.allowed();
- match rule.allowed() {
- ResolvedDelegates::Delegates(_) => {
- // This is the expected case, so we continue to validate the threshold.
- }
- ResolvedDelegates::Set(actual) => {
- return Err(CanonicalRefsError::DefaultBranchRuleError(
- DefaultBranchRuleError::Allowed {
- pattern: pattern.to_string(),
- actual: actual
- .iter()
- .map(|s| s.to_string())
- .collect::<Vec<_>>()
- .join(", "),
- },
- ));
- }
- }
- let actual = (*rule.threshold()).into();
- let expected = self.threshold();
- if actual != expected {
- return Err(CanonicalRefsError::DefaultBranchRuleError(
- DefaultBranchRuleError::Threshold {
- pattern: pattern.to_string(),
- actual,
- expected,
- },
- ));
- }
- Ok(())
- }
-
- /// Synthesize a `HEAD` symbolic reference and a default branch rule
- /// from the project payload.
- fn synthesize_head(&self, crefs: CanonicalRefs, project: &Project) -> RawCanonicalRefs {
- let default_branch = project.default_branch_qualified();
-
- let add_rule = crefs.rules().matches(&default_branch).next().is_none();
-
- let mut raw_crefs = RawCanonicalRefs::from(crefs);
-
- if add_rule {
- raw_crefs.raw_rules_mut().insert(
- git::fmt::refspec::QualifiedPattern::from(default_branch.to_owned()),
- rules::Rule::new(rules::Allowed::Delegates, self.threshold()),
- );
- }
-
- raw_crefs
- .symbolic_mut()
- .insert(git::fmt::refname!("HEAD"), default_branch.to_ref_string());
+ .ok_or(CanonicalRefsError::Missing)?
+ .map_err(CanonicalRefsError::Payload)?;
+ let resolve = &mut || self.delegates.clone();
- raw_crefs
+ Ok(raw_crefs.try_into_canonical_refs(resolve)?)
}
/// Return the associated [`Visibility`] of this document.
pub fn visibility(&self) -> &Visibility {
- &self.visibility
+ &self.view.visibility
}
/// Check whether the visibility of the document is public.
pub fn is_public(&self) -> bool {
- self.visibility.is_public()
+ self.visibility().is_public()
}
/// Check whether the visibility of the document is private.
pub fn is_private(&self) -> bool {
- self.visibility.is_private()
- }
-
- /// Return the associated threshold of this document.
- pub fn threshold(&self) -> usize {
- self.threshold.into()
- }
-
- /// Return the associated threshold of this document in its non-zero format.
- pub fn threshold_nonzero(&self) -> &NonZeroUsize {
- &self.threshold.0
+ self.visibility().is_private()
}
/// Return the associated delegates of this document.
@@ -961,7 +806,7 @@ impl Doc {
/// Check whether this document and the associated repository is visible to
/// the given peer.
pub fn is_visible_to(&self, did: &Did) -> bool {
- match &self.visibility {
+ match self.visibility() {
Visibility::Public => true,
Visibility::Private { allow } => allow.contains(did) || self.is_delegate(did),
}
@@ -1082,36 +927,8 @@ pub enum CanonicalRefsError {
#[error(transparent)]
CanonicalRefs(#[from] crefs::ValidationError),
- #[error("could not load `xyz.radicle.project` to get default branch name: {0}")]
- ProjectPayload(PayloadError),
-
- #[error("payload `xyz.radicle.project` is missing")]
- SynthesisPayloadMissing,
-
- #[error(transparent)]
- DefaultBranchRuleError(#[from] DefaultBranchRuleError),
-}
-
-#[derive(Debug, Error)]
-pub enum DefaultBranchRuleError {
- #[error(
- "rule for pattern '{pattern}' which matches the target of symbolic reference 'HEAD' (possibly synthesized from payload 'xyz.radicle.project') must use 'allow' value of \"delegates\" but uses {actual}"
- )]
- Allowed { pattern: String, actual: String },
-
- #[error(
- "rule for pattern '{pattern}' which matches the target of symbolic reference 'HEAD' (possibly synthesized from payload 'xyz.radicle.project') must use a threshold of {expected} as required by the identity document but uses {actual}"
- )]
- Threshold {
- pattern: String,
- actual: usize,
- expected: usize,
- },
-
- #[error(
- "target symbolic reference 'HEAD' ('{cref}') does not match `defaultBranch` from payload `xyz.radicle.project` ('{project}')"
- )]
- HeadMismatch { cref: RefString, project: RefString },
+ #[error("identity document is missing the `xyz.radicle.crefs` payload")]
+ Missing,
}
#[cfg(test)]
@@ -1136,7 +953,13 @@ mod test {
fn duplicate_dids() {
let delegate = SigningKey::mock(usize::MAX);
let did = Did::from(delegate.public_key());
- let mut doc = RawDoc::new(r#gen::<Project>(1), vec![did], 1, Visibility::Public);
+ let mut doc = RawDoc::new(
+ r#gen::<Project>(1),
+ vec![did],
+ &git::fmt::refname!("master"),
+ 1,
+ Visibility::Public,
+ );
doc.delegate(did);
let doc = doc.verified().unwrap();
assert!(doc.delegates().len() == 1, "Duplicate DID was not removed");
@@ -1154,16 +977,214 @@ mod test {
let doc = RawDoc::new(
r#gen::<Project>(1),
delegates[0..MAX_DELEGATES].into(),
+ &git::fmt::refname!("master"),
1,
Visibility::Public,
);
assert_matches!(doc.verified(), Ok(_));
// A document that exceeds max delegates should fail
- let doc = RawDoc::new(r#gen::<Project>(1), delegates, 1, Visibility::Public);
+ let doc = RawDoc::new(
+ r#gen::<Project>(1),
+ delegates,
+ &git::fmt::refname!("master"),
+ 1,
+ Visibility::Public,
+ );
assert_matches!(doc.verified(), Err(DocError::Delegates(DelegatesError(_))));
}
+ // The write-quorum invariant (`1 <= threshold <= |allowed|`) is enforced by
+ // `verified()` itself, so it holds for every `Doc` — including revisions
+ // adopted over the network via `Doc::from_blob` — not only for documents
+ // that pass the CLI's `update::verify`.
+ #[test]
+ fn verified_rejects_threshold_exceeding_delegates() {
+ // A single-delegate document whose default-branch rule demands a
+ // threshold of 2 makes the branch immutable and must be rejected.
+ let did = r#gen::<Did>(1);
+ let doc = RawDoc::new(
+ r#gen::<Project>(1),
+ vec![did],
+ &git::fmt::refname!("master"),
+ 2,
+ Visibility::Public,
+ );
+ assert_matches!(doc.verified(), Err(DocError::DefaultBranch(_)));
+ }
+
+ #[test]
+ fn verified_rejects_missing_crefs() {
+ // Without the `xyz.radicle.crefs` payload there is no default branch or
+ // write quorum, so the document must not verify.
+ let mut doc = RawDoc::new(
+ r#gen::<Project>(1),
+ vec![r#gen::<Did>(1)],
+ &git::fmt::refname!("master"),
+ 1,
+ Visibility::Public,
+ );
+ doc.payload_mut().remove(PayloadId::canonical_refs());
+ assert_matches!(doc.verified(), Err(DocError::DefaultBranch(_)));
+ }
+
+ /// A version-1 document as a released client wrote it.
+ fn v1_golden() -> serde_json::Value {
+ json!({
+ "payload": {
+ "xyz.radicle.project": {
+ "defaultBranch": "master",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "name": "heartwood"
+ }
+ },
+ "delegates": ["did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"],
+ "threshold": 1
+ })
+ }
+
+ #[test]
+ fn migrated_view_governs_default_branch() {
+ // The migration moves the default branch and its quorum into the crefs
+ // payload, and drops `defaultBranch` from the project payload.
+ let doc = serde_json::from_value::<Doc>(v1_golden()).unwrap();
+ let crefs = doc.canonical_refs().unwrap();
+
+ assert_eq!(
+ crefs.symbolic().resolve_head().unwrap().as_str(),
+ "refs/heads/master"
+ );
+ let (pattern, rule) = crefs
+ .rules()
+ .matches(&doc.default_branch().unwrap())
+ .next()
+ .unwrap();
+ assert_eq!(pattern.as_str(), "refs/heads/master");
+ assert_eq!(usize::from(*rule.threshold()), 1);
+ assert!(
+ doc.payload()
+ .get(PayloadId::project())
+ .unwrap()
+ .get("defaultBranch")
+ .is_none(),
+ "the migrated view must not carry `defaultBranch`"
+ );
+ // The project payload still deserializes, minus the moved field.
+ assert_eq!(doc.project().unwrap().unwrap().name(), "heartwood");
+ }
+
+ #[test]
+ fn migrate_is_stable() {
+ let doc = serde_json::from_value::<Doc>(v1_golden()).unwrap();
+ let migrated = doc.migrated().unwrap();
+
+ assert_eq!(migrated.version(), IDENTITY_VERSION);
+ // Migrating what is already migrated changes nothing, so a repeated
+ // `rad id migrate` cannot drift.
+ assert_eq!(migrated.migrated().unwrap(), migrated);
+ // The view is the same whichever side it is read from.
+ assert_eq!(doc.payload(), migrated.payload());
+ }
+
+ #[test]
+ fn migration_revision_differs_from_parent() {
+ // The migration changes the stored document, so `DocUnchanged` does not
+ // fire when the revision is applied.
+ let doc = serde_json::from_value::<Doc>(v1_golden()).unwrap();
+ let migrated = doc.migrated().unwrap();
+
+ assert_ne!(doc, migrated);
+ assert_ne!(doc.encode().unwrap().0, migrated.encode().unwrap().0);
+ }
+
+ #[test]
+ fn version_2_rejects_default_branch() {
+ // `Project` swallows unknown fields, so a stray `defaultBranch` would be
+ // silently ignored rather than disallowed without an explicit check.
+ let doc = json!({
+ "version": 2,
+ "payload": {
+ "xyz.radicle.project": {
+ "name": "heartwood",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "defaultBranch": "master"
+ },
+ "xyz.radicle.crefs": {
+ "symbolic": { "HEAD": "refs/heads/master" },
+ "rules": {
+ "refs/heads/master": { "allow": "delegates", "threshold": 1 }
+ }
+ }
+ },
+ "delegates": ["did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"]
+ });
+ assert_matches!(
+ serde_json::from_value::<Doc>(doc),
+ Err(_),
+ "a version 2 document must not carry `defaultBranch`"
+ );
+ }
+
+ #[test]
+ fn version_2_rejects_threshold() {
+ // The quorum lives in the crefs rule; a top-level `threshold` would be a
+ // second, silently ignored source of truth.
+ let doc = json!({
+ "version": 2,
+ "payload": {
+ "xyz.radicle.crefs": {
+ "symbolic": { "HEAD": "refs/heads/master" },
+ "rules": {
+ "refs/heads/master": { "allow": "delegates", "threshold": 1 }
+ }
+ }
+ },
+ "delegates": ["did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"],
+ "threshold": 1
+ });
+ assert_matches!(serde_json::from_value::<RawDoc>(doc), Err(_));
+ }
+
+ #[test]
+ fn version_1_head_must_agree_with_default_branch() {
+ // Version 1 allowed a crefs payload alongside `defaultBranch`, as long
+ // as the two agreed. A document that never was valid must not become
+ // valid by migrating.
+ let doc = json!({
+ "payload": {
+ "xyz.radicle.project": {
+ "name": "heartwood",
+ "description": "Radicle Heartwood Protocol & Stack",
+ "defaultBranch": "master"
+ },
+ "xyz.radicle.crefs": {
+ "symbolic": { "HEAD": "refs/heads/main" },
+ "rules": {
+ "refs/heads/main": { "allow": "delegates", "threshold": 1 }
+ }
+ }
+ },
+ "delegates": ["did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"],
+ "threshold": 1
+ });
+ assert_matches!(
+ serde_json::from_value::<Doc>(doc),
+ Err(_),
+ "`HEAD` disagreeing with `defaultBranch` must be rejected"
+ );
+ }
+
+ #[test]
+ fn edit_keeps_stored_version() {
+ // An ordinary edit of a version-1 document proposes another version-1
+ // document; only `rad id migrate` changes the version.
+ let doc = serde_json::from_value::<Doc>(v1_golden()).unwrap();
+ let edited = doc.with_edits(|raw| raw.delegate(r#gen::<Did>(1))).unwrap();
+
+ assert_eq!(edited.version(), Version::new(1).unwrap());
+ assert_eq!(edited.delegates().len(), 2);
+ }
+
#[test]
fn is_valid_version() {
// 0 is not a valid version
@@ -1211,8 +1232,8 @@ mod test {
}
);
- // Deserializing the `RawDoc` should not fail and should include the
- // `IDENTITY_VERSION`.
+ // Deserializing the `RawDoc` should not fail, and a document without a
+ // `version` field is the original (version 1) format.
let doc = serde_json::from_str::<RawDoc>(&v1.to_string()).unwrap();
let payload = [(
PayloadId::project().clone(),
@@ -1237,30 +1258,45 @@ mod test {
.parse::<Did>()
.unwrap(),
];
- // And this is the expected outcome of the deserialization
+ // And this is the expected outcome of the deserialization.
assert_eq!(
doc,
- RawDoc {
- version: IDENTITY_VERSION,
+ RawDoc::V1(v1::Doc {
payload: payload.clone(),
delegates: delegates.clone(),
threshold: 1,
visibility: Visibility::Public,
- }
+ })
);
- // Deserializing into `Doc` should also succeed.
- let verified = serde_json::from_str::<Doc>(&v1.to_string()).unwrap();
- let delegates = Delegates(NonEmpty::from_vec(delegates).unwrap());
+ // A version 1 document verifies, and its view exposes the default
+ // branch and quorum the version-1 fields described.
+ let verified = doc.clone().verified().unwrap();
+ assert_eq!(verified.version(), Version::new(1).unwrap());
assert_eq!(
- verified,
- Doc {
- version: IDENTITY_VERSION,
- threshold: Threshold::new(1, &delegates).unwrap(),
- payload: payload.clone(),
- delegates,
- visibility: Visibility::Public,
- }
+ verified.default_branch().unwrap().as_str(),
+ "refs/heads/master"
+ );
+ let crefs = verified.canonical_refs().unwrap();
+ let (_, rule) = crefs
+ .rules()
+ .matches(&verified.default_branch().unwrap())
+ .next()
+ .unwrap();
+ assert_eq!(usize::from(*rule.threshold()), 1);
+
+ // Deserializing directly into `Doc` gives the same document.
+ assert_eq!(
+ serde_json::from_str::<Doc>(&v1.to_string()).unwrap(),
+ verified
+ );
+
+ // The stored form is unchanged, so re-encoding a version 1 document
+ // reproduces the bytes a released client wrote.
+ let (_, bytes) = verified.encode().unwrap();
+ assert_eq!(
+ serde_json::from_slice::<serde_json::Value>(&bytes).unwrap(),
+ v1
);
}
@@ -1290,9 +1326,9 @@ mod test {
);
assert_eq!(
(*id).to_string(),
- "d96f425412c9f8ad5d9a9a05c9831d0728e2338d"
+ "f10bd9e36848dc4eb70cc078d1d0bbaac7c1ba61"
);
- assert_eq!(id.urn(), String::from("rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji"));
+ assert_eq!(id.urn(), String::from("rad:z4MmvDgm9DoJF6ecPSt55geCbNp4G"));
}
#[test]
@@ -1409,6 +1445,7 @@ mod test {
fn default_branch_without_project() {
let value = serde_json::json!(
{
+ "version": 2,
"payload": {
"xyz.radicle.crefs": {
"symbolic": {
@@ -1424,8 +1461,7 @@ mod test {
},
"delegates": [
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
- ],
- "threshold": 1
+ ]
}
);
@@ -1433,43 +1469,46 @@ mod test {
assert_eq!(doc.default_branch().unwrap().as_str(), "refs/heads/main");
}
+ /// Version 2 leaves the rule governing `HEAD` free: it may name explicit
+ /// DIDs instead of `delegates`, and it may set its own threshold. The rule
+ /// that governs `HEAD` is the most specific match, not the first one the
+ /// glob happens to yield.
#[test]
- fn default_branch_clash() {
+ fn head_rule_is_the_most_specific_match() {
let value = serde_json::json!(
{
+ "version": 2,
"payload": {
- "xyz.radicle.project": {
- "name": "example",
- "description": "An example project",
- "defaultBranch": "main",
- },
"xyz.radicle.crefs": {
"symbolic": {
- "HEAD": "refs/heads/master",
+ "HEAD": "refs/heads/main",
},
"rules": {
- "refs/heads/master": {
+ "refs/heads/*": {
"allow": "delegates",
+ "threshold": 2,
+ },
+ "refs/heads/main": {
+ "allow": ["did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"],
"threshold": 1,
}
}
}
},
"delegates": [
- "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM"
- ],
- "threshold": 1
+ "did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
+ "did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT"
+ ]
}
);
let doc = serde_json::from_value::<Doc>(value).unwrap();
- assert_matches!(
- doc.default_branch(),
- Err(DefaultBranchError::CanonicalRefsError(
- CanonicalRefsError::DefaultBranchRuleError(
- DefaultBranchRuleError::HeadMismatch { .. }
- )
- ))
- );
+ assert_eq!(doc.default_branch().unwrap().as_str(), "refs/heads/main");
+
+ let crefs = doc.canonical_refs().unwrap();
+ let head = crefs.symbolic().resolve_head().unwrap();
+ let (pattern, rule) = crefs.rules().matches(head).next().unwrap();
+ assert_eq!(pattern.to_string(), "refs/heads/main");
+ assert_eq!(usize::from(*rule.threshold()), 1);
}
}
diff --git a/crates/radicle/src/identity/doc/migrate.rs b/crates/radicle/src/identity/doc/migrate.rs
new file mode 100644
index 0000000000..bcb6e73f33
--- /dev/null
+++ b/crates/radicle/src/identity/doc/migrate.rs
@@ -0,0 +1,210 @@
+//! Migration between the stored identity document schemas.
+
+use serde_json as json;
+
+use crate::git;
+use crate::git::canonical::rules::{self, ResolvedDelegates};
+use crate::git::fmt::{Qualified, RefString};
+use crate::identity::crefs::{CanonicalRefs, RawCanonicalRefs};
+
+use super::{
+ CanonicalRefsError, Delegates, DelegatesError, GetPayload as _, Payload, PayloadId, v1, v2,
+};
+
+/// Transform a stored identity document into the schema that follows it.
+///
+/// The transform is deterministic: the same stored document always yields the
+/// same result. One implementation therefore serves both the view every reader
+/// consumes and the revision `rad id migrate` proposes, so the implicit and the
+/// explicit migration cannot drift apart.
+pub trait Migrate {
+ /// The schema this document migrates to.
+ type Next;
+ /// Why a document cannot be migrated.
+ type Error;
+
+ /// Migrate the document to [`Migrate::Next`].
+ fn migrate(self) -> Result<Self::Next, Self::Error>;
+}
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("json: {0}")]
+ Json(#[from] json::Error),
+
+ #[error(transparent)]
+ CanonicalRefs(#[from] CanonicalRefsError),
+
+ #[error(transparent)]
+ DefaultBranchRule(#[from] DefaultBranchRuleError),
+
+ #[error(transparent)]
+ Delegates(#[from] DelegatesError),
+
+ #[error(
+ "no default branch to migrate: the `xyz.radicle.project` payload defines no `defaultBranch` and the `xyz.radicle.crefs` payload defines no `HEAD` symbolic reference"
+ )]
+ MissingDefaultBranch,
+}
+
+/// The version-1 rule governing the default branch disagrees with the rest of
+/// the document, so there is no single quorum to carry over.
+#[derive(Debug, thiserror::Error)]
+pub enum DefaultBranchRuleError {
+ #[error(
+ "rule for pattern '{pattern}' which matches the target of symbolic reference 'HEAD' must use 'allow' value of \"delegates\" but uses {actual}"
+ )]
+ Allowed { pattern: String, actual: String },
+
+ #[error(
+ "rule for pattern '{pattern}' which matches the target of symbolic reference 'HEAD' must use a threshold of {expected} as required by the identity document but uses {actual}"
+ )]
+ Threshold {
+ pattern: String,
+ actual: usize,
+ expected: usize,
+ },
+
+ #[error(
+ "target of symbolic reference 'HEAD' ('{cref}') does not match `defaultBranch` from payload `xyz.radicle.project` ('{project}')"
+ )]
+ HeadMismatch { cref: RefString, project: RefString },
+}
+
+impl Migrate for v1::Doc {
+ type Next = v2::Doc;
+ type Error = Error;
+
+ /// Move the default branch and its write quorum into the
+ /// `xyz.radicle.crefs` payload, and drop the top-level `threshold`.
+ ///
+ /// A version-1 document could already carry a crefs payload, in which case
+ /// its `HEAD` had to agree with `defaultBranch` and its rule with the
+ /// document's `threshold`. That invariant is checked here rather than
+ /// papered over, so a document that never was valid does not become valid
+ /// by migrating.
+ fn migrate(mut self) -> Result<Self::Next, Self::Error> {
+ let threshold = self.threshold;
+ let default_branch = self.default_branch();
+ let mut crefs = self
+ .raw_canonical_refs()
+ .transpose()
+ .map_err(CanonicalRefsError::Payload)?
+ .unwrap_or_default();
+ // Rules can only be matched against once validated, and validation
+ // also resolves any `HEAD` chain. `crefs` is mutated when synthesizing,
+ // so validate a copy.
+ let valid = {
+ let delegates = Delegates::new(self.delegates.iter().copied())?;
+ let resolve = &mut || delegates.clone();
+ crefs
+ .clone()
+ .try_into_canonical_refs(resolve)
+ .map_err(CanonicalRefsError::CanonicalRefs)?
+ };
+ let head = valid.symbolic().resolve_head().cloned();
+
+ let synthesized = match (head, default_branch) {
+ (Some(head), Some(branch)) => {
+ let project_branch = git::refs::branch(&branch);
+ if project_branch != head {
+ return Err(DefaultBranchRuleError::HeadMismatch {
+ cref: head.to_ref_string(),
+ project: project_branch.to_ref_string(),
+ }
+ .into());
+ }
+ validate_head_rule(&valid, &head, threshold)?;
+ false
+ }
+ (Some(head), None) => {
+ validate_head_rule(&valid, &head, threshold)?;
+ false
+ }
+ (None, Some(branch)) => {
+ synthesize_head(&mut crefs, &valid, &branch, threshold);
+ true
+ }
+ (None, None) => return Err(Error::MissingDefaultBranch),
+ };
+
+ // The crefs payload is the sole authority from here on.
+ self.remove_default_branch();
+
+ let v1::Doc {
+ mut payload,
+ delegates,
+ visibility,
+ threshold: _,
+ } = self;
+
+ if synthesized {
+ payload.insert(
+ PayloadId::canonical_refs().clone(),
+ Payload::from(json::to_value(crefs)?),
+ );
+ }
+
+ Ok(v2::Doc {
+ payload,
+ delegates,
+ visibility,
+ })
+ }
+}
+
+/// Check that the rule matching `HEAD`'s target uses `delegates` and the
+/// document's `threshold`.
+///
+/// A `HEAD` with no matching rule dangles; that is reported by canonical
+/// references validation, which sees the migrated document.
+fn validate_head_rule(
+ crefs: &CanonicalRefs,
+ head: &Qualified,
+ threshold: usize,
+) -> Result<(), DefaultBranchRuleError> {
+ let Some((pattern, rule)) = crefs.rules().matches(head).next() else {
+ return Ok(());
+ };
+
+ if let ResolvedDelegates::Set(actual) = rule.allowed() {
+ return Err(DefaultBranchRuleError::Allowed {
+ pattern: pattern.to_string(),
+ actual: actual
+ .iter()
+ .map(|did| did.to_string())
+ .collect::<Vec<_>>()
+ .join(", "),
+ });
+ }
+ let actual = usize::from(*rule.threshold());
+ if actual != threshold {
+ return Err(DefaultBranchRuleError::Threshold {
+ pattern: pattern.to_string(),
+ actual,
+ expected: threshold,
+ });
+ }
+ Ok(())
+}
+
+/// Add a `HEAD` symbolic reference for `branch`, and a rule governing it if
+/// none matches already.
+fn synthesize_head(
+ crefs: &mut RawCanonicalRefs,
+ valid: &CanonicalRefs,
+ branch: &RefString,
+ threshold: usize,
+) {
+ let qualified = git::refs::branch(branch);
+
+ if valid.rules().matches(&qualified).next().is_none() {
+ crefs.raw_rules_mut().insert(
+ v2::branch_pattern(branch),
+ rules::Rule::new(rules::Allowed::Delegates, threshold),
+ );
+ }
+ crefs
+ .symbolic_mut()
+ .insert(git::fmt::refname!("HEAD"), qualified.to_ref_string());
+}
diff --git a/crates/radicle/src/identity/doc/raw.rs b/crates/radicle/src/identity/doc/raw.rs
new file mode 100644
index 0000000000..ebf5a84820
--- /dev/null
+++ b/crates/radicle/src/identity/doc/raw.rs
@@ -0,0 +1,306 @@
+//! The identity document as it is stored, at whichever version wrote it.
+
+use std::collections::BTreeMap;
+use std::ops::Not;
+
+use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
+use serde_json as json;
+
+use crate::git::fmt::RefString;
+use crate::identity::{Did, project::Project};
+
+use super::migrate::Migrate as _;
+use super::{
+ Delegates, Doc, DocError, GetPayload, Payload, PayloadId, Version, Visibility, migrate,
+ missing_version, v1, v2,
+};
+
+/// `RawDoc` is similar to the [`Doc`] type, however, it can be edited and may
+/// not be valid.
+///
+/// It is expected that any changes to a [`Doc`] are made via [`RawDoc`], and
+/// then verified by using [`RawDoc::verified`].
+///
+/// Each variant is a *stored* schema — the bytes a client of that version
+/// wrote, hashed and signed. Editing and re-serializing a `RawDoc` keeps its
+/// version, so an ordinary edit of an older document does not silently migrate
+/// it. [`Doc::migrated`] performs the explicit migration, which goes through
+/// the usual delegate vote.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum RawDoc {
+ V1(v1::Doc),
+ V2(v2::Doc),
+}
+
+/// Apply `$body` to the inner document of either variant.
+macro_rules! dispatch {
+ ($doc:expr, |$inner:ident| $body:expr) => {
+ match $doc {
+ RawDoc::V1($inner) => $body,
+ RawDoc::V2($inner) => $body,
+ }
+ };
+}
+
+impl<'de> Deserialize<'de> for RawDoc {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ // Serde's internally-tagged enums need a *string* tag, but `version` is
+ // a number, so the variant is chosen by hand.
+ let value = json::Value::deserialize(deserializer)?;
+ let version = match value.get("version") {
+ // A document written before `version` was introduced is version 1.
+ None => missing_version(),
+ // `Version::new` rejects `0` and anything past `IDENTITY_VERSION`.
+ Some(version) => Version::deserialize(version).map_err(de::Error::custom)?,
+ };
+
+ match u32::from(version) {
+ 1 => json::from_value(value)
+ .map(RawDoc::V1)
+ .map_err(de::Error::custom),
+ 2 => {
+ if value.get("threshold").is_some() {
+ return Err(de::Error::custom(
+ "a version 2 identity document must not define a top-level `threshold`; \
+ the write quorum is governed by the `xyz.radicle.crefs` payload",
+ ));
+ }
+ json::from_value(value)
+ .map(RawDoc::V2)
+ .map_err(de::Error::custom)
+ }
+ // N.b. `Version` cannot hold any other number, so this is
+ // unreachable until a version 3 schema is added.
+ version => Err(de::Error::custom(format!(
+ "unsupported identity document version {version}"
+ ))),
+ }
+ }
+}
+
+impl Serialize for RawDoc {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ dispatch!(self, |doc| doc.serialize(serializer))
+ }
+}
+
+impl RawDoc {
+ /// Construct a new [`RawDoc`] at [`IDENTITY_VERSION`], with an initial
+ /// payload containing the provided [`Project`] and a `xyz.radicle.crefs`
+ /// payload governing `default_branch` at the given `threshold`, with the
+ /// given `delegates` and `visibility`.
+ ///
+ /// [`IDENTITY_VERSION`]: super::IDENTITY_VERSION
+ pub fn new(
+ project: Project,
+ delegates: Vec<Did>,
+ default_branch: &RefString,
+ threshold: usize,
+ visibility: Visibility,
+ ) -> Self {
+ Self::new_at(
+ super::IDENTITY_VERSION,
+ project,
+ delegates,
+ default_branch,
+ threshold,
+ visibility,
+ )
+ }
+
+ /// Like [`RawDoc::new`], but at the given document `version`.
+ ///
+ /// Creating a version-1 document is deliberate: it stays readable to
+ /// releases that predate version 2.
+ pub fn new_at(
+ version: Version,
+ project: Project,
+ delegates: Vec<Did>,
+ default_branch: &RefString,
+ threshold: usize,
+ visibility: Visibility,
+ ) -> Self {
+ let project =
+ json::to_value(project).expect("RawDoc::new_at: payload must be serializable");
+
+ match u32::from(version) {
+ 1 => {
+ let mut project = project;
+ if let Some(object) = project.as_object_mut() {
+ object.insert(
+ "defaultBranch".to_owned(),
+ json::Value::from(default_branch.as_str()),
+ );
+ }
+ Self::V1(v1::Doc {
+ payload: BTreeMap::from_iter([(
+ PayloadId::project().clone(),
+ Payload::from(project),
+ )]),
+ delegates,
+ threshold,
+ visibility,
+ })
+ }
+ _ => Self::V2(v2::Doc {
+ payload: BTreeMap::from_iter([
+ (PayloadId::project().clone(), Payload::from(project)),
+ (
+ PayloadId::canonical_refs().clone(),
+ v2::default_branch_crefs(default_branch, threshold),
+ ),
+ ]),
+ delegates,
+ visibility,
+ }),
+ }
+ }
+
+ /// Get the version of the document.
+ pub fn version(&self) -> Version {
+ match self {
+ Self::V1(_) => missing_version(),
+ Self::V2(_) => super::IDENTITY_VERSION,
+ }
+ }
+
+ /// Return the associated payloads for this document.
+ pub fn payload(&self) -> &BTreeMap<PayloadId, Payload> {
+ dispatch!(self, |doc| &doc.payload)
+ }
+
+ /// Return the associated payloads for mutation.
+ pub fn payload_mut(&mut self) -> &mut BTreeMap<PayloadId, Payload> {
+ dispatch!(self, |doc| &mut doc.payload)
+ }
+
+ /// Return the associated delegates for this document.
+ pub fn delegates(&self) -> &Vec<Did> {
+ dispatch!(self, |doc| &doc.delegates)
+ }
+
+ /// Return the associated delegates for mutation.
+ ///
+ /// The delegates are only checked by [`RawDoc::verified`], so an
+ /// intermediate edit may leave the set empty or oversized.
+ pub fn delegates_mut(&mut self) -> &mut Vec<Did> {
+ dispatch!(self, |doc| &mut doc.delegates)
+ }
+
+ /// Return the associated [`Visibility`] of this document.
+ pub fn visibility(&self) -> &Visibility {
+ dispatch!(self, |doc| &doc.visibility)
+ }
+
+ /// Return the associated [`Visibility`] for mutation.
+ pub fn visibility_mut(&mut self) -> &mut Visibility {
+ dispatch!(self, |doc| &mut doc.visibility)
+ }
+
+ /// Set the number of delegates required to accept a change to the default
+ /// branch.
+ ///
+ /// Where the threshold is stored depends on the version: version 1 has a
+ /// top-level field, while version 2 keeps it in the `xyz.radicle.crefs`
+ /// rule governing `HEAD`.
+ pub fn set_threshold(&mut self, threshold: usize) {
+ match self {
+ Self::V1(doc) => doc.threshold = threshold,
+ Self::V2(doc) => doc.set_threshold(threshold),
+ }
+ }
+
+ /// Check if the given `did` is in the set of delegates.
+ pub fn is_delegate(&self, did: &Did) -> bool {
+ self.delegates().contains(did)
+ }
+
+ /// Add a new delegate to the document.
+ ///
+ /// Note that if this `Did` is a duplicate, then the resulting set will only
+ /// show it once.
+ pub fn delegate(&mut self, did: Did) {
+ self.delegates_mut().push(did)
+ }
+
+ /// Remove the `did` from the set of delegates. Returns `true` if it was
+ /// removed.
+ pub fn rescind(&mut self, did: &Did) -> Result<bool, DocError> {
+ let delegates = self.delegates_mut();
+ let (matches, remaining) = delegates.iter().partition(|d| *d == did);
+ *delegates = remaining;
+
+ Ok(matches.is_empty().not())
+ }
+
+ /// Construct the `RawDoc` from the set of `bytes` that are expected to be
+ /// in JSON format.
+ pub fn from_json(bytes: &[u8]) -> Result<Self, DocError> {
+ json::from_slice(bytes).map_err(DocError::from)
+ }
+
+ /// The document migrated to [`IDENTITY_VERSION`], which is what every
+ /// reader consumes.
+ ///
+ /// [`IDENTITY_VERSION`]: super::IDENTITY_VERSION
+ pub fn view(&self) -> Result<v2::Doc, migrate::Error> {
+ match self {
+ Self::V1(doc) => doc.clone().migrate(),
+ Self::V2(doc) => Ok(doc.clone()),
+ }
+ }
+
+ /// Verify the `RawDoc`'s values, converting it into a valid [`Doc`].
+ ///
+ /// The verifications are as follows:
+ ///
+ /// - The delegates: any duplicates are removed, and for the remaining set
+ /// ensure that it is non-empty and does not exceed a length of
+ /// [`MAX_DELEGATES`].
+ /// - The document migrates to [`IDENTITY_VERSION`]. For version 1 this
+ /// also checks the version-1 invariants that tie `defaultBranch`, the
+ /// top-level `threshold` and the crefs payload together.
+ /// - The migrated document satisfies the version-2 invariants: the
+ /// `xyz.radicle.project` payload defines no `defaultBranch`, and the
+ /// `xyz.radicle.crefs` payload is present, valid, and defines a
+ /// resolvable default branch whose rule has a well-formed write quorum
+ /// (`1 <= threshold <= |allowed|`).
+ ///
+ /// [`MAX_DELEGATES`]: super::MAX_DELEGATES
+ /// [`IDENTITY_VERSION`]: super::IDENTITY_VERSION
+ pub fn verified(self) -> Result<Doc, DocError> {
+ let delegates = Delegates::new(self.delegates().iter().copied())?;
+ let view = self.view()?;
+ view.validate()?;
+
+ let doc = Doc {
+ raw: self,
+ view,
+ delegates,
+ };
+ // Validate here so that *every* verified `Doc` — including those adopted
+ // over the network via `Doc::from_blob` and those obtained by
+ // deserializing — carries an enforceable quorum, rather than deferring
+ // the check to the CLI-only `update::verify`.
+ doc.default_branch()?;
+
+ Ok(doc)
+ }
+}
+
+impl GetPayload for RawDoc {
+ fn get_payload(&self, id: &PayloadId) -> Option<&Payload> {
+ self.payload().get(id)
+ }
+}
+
+impl TryFrom<RawDoc> for Doc {
+ type Error = DocError;
+
+ fn try_from(doc: RawDoc) -> Result<Self, Self::Error> {
+ doc.verified()
+ }
+}
diff --git a/crates/radicle/src/identity/doc/update.rs b/crates/radicle/src/identity/doc/update.rs
index cc3ee8a9b6..b47ef6a792 100644
--- a/crates/radicle/src/identity/doc/update.rs
+++ b/crates/radicle/src/identity/doc/update.rs
@@ -39,20 +39,30 @@ impl FromStr for EditVisibility {
/// Change the visibility of the [`RawDoc`], using the provided
/// [`EditVisibility`].
pub fn visibility(mut raw: RawDoc, edit: EditVisibility) -> RawDoc {
- match (&mut raw.visibility, edit) {
+ match (raw.visibility(), edit) {
(Visibility::Public, EditVisibility::Public) => raw,
(Visibility::Private { .. }, EditVisibility::Private) => raw,
(Visibility::Public, EditVisibility::Private) => {
- raw.visibility = Visibility::private([]);
+ *raw.visibility_mut() = Visibility::private([]);
raw
}
(Visibility::Private { .. }, EditVisibility::Public) => {
- raw.visibility = Visibility::Public;
+ *raw.visibility_mut() = Visibility::Public;
raw
}
}
}
+/// Set the number of delegates required to accept a change to the default
+/// branch.
+///
+/// Where the threshold is stored depends on the document version, which
+/// [`RawDoc::set_threshold`] takes care of.
+pub fn threshold(mut raw: RawDoc, threshold: usize) -> RawDoc {
+ raw.set_threshold(threshold);
+ raw
+}
+
/// Change the `allow` set of a document if the visibility is set to
/// [`Visibility::Private`].
///
@@ -83,7 +93,7 @@ pub fn privacy_allow_list(
return Err(error::PrivacyAllowList::Overlapping(overlap));
}
- match &mut raw.visibility {
+ match raw.visibility_mut() {
Visibility::Public => Err(error::PrivacyAllowList::PublicVisibility),
Visibility::Private { allow: existing } => {
for did in allow {
@@ -122,9 +132,10 @@ pub fn delegates(
return Ok(Ok(raw));
}
- raw.delegates = raw
- .delegates
- .into_iter()
+ let delegates = raw.delegates_mut();
+ *delegates = delegates
+ .iter()
+ .copied()
.chain(additions)
.filter(|d| !removals.contains(d))
.collect::<Vec<_>>();
@@ -167,7 +178,7 @@ pub fn payload(
upserts: impl IntoIterator<Item = PayloadUpsert>,
) -> Result<RawDoc, error::PayloadError> {
for PayloadUpsert { id, key, value } in upserts {
- if let Some(ref mut payload) = raw.payload.get_mut(&id) {
+ if let Some(ref mut payload) = raw.payload_mut().get_mut(&id) {
if let Some(obj) = payload.as_object_mut() {
if value.is_null() {
obj.remove(&key);
@@ -178,7 +189,7 @@ pub fn payload(
return Err(error::PayloadError::ExpectedObject { id });
}
} else {
- raw.payload
+ raw.payload_mut()
.insert(id, serde_json::json!({ key: value }).into());
}
}
@@ -195,68 +206,24 @@ pub fn payload(
/// [`CanonicalRefs`]: crate::identity::CanonicalRefs
pub fn verify(raw: RawDoc) -> Result<Doc, error::DocVerification> {
let proposal = raw.clone().verified()?;
- // Verify that the project payload is valid
+ // Verify that the project payload, if present, deserializes correctly.
// TODO(finto): perhaps this should be handled by JSON Schemas instead
- let project = match proposal.project() {
- None => None,
- Some(Ok(project)) => Some(project),
- Some(Err(PayloadError::Json(e))) => {
- return Err(error::DocVerification::PayloadError {
- id: PayloadId::project().clone(),
- err: e.to_string(),
- });
- }
- };
-
- let resolve = &mut || proposal.delegates.clone();
-
- let crefs = match proposal.raw_canonical_refs() {
- None => None,
- Some(Ok(crefs)) => match crefs.try_into_canonical_refs(resolve) {
- Ok(crefs) => Some(crefs),
- Err(err) => {
- return Err(error::DocVerification::PayloadError {
- id: PayloadId::canonical_refs().clone(),
- err: err.to_string(),
- });
- }
- },
- Some(Err(PayloadError::Json(e))) => {
- return Err(error::DocVerification::PayloadError {
- id: PayloadId::canonical_refs().clone(),
- err: e.to_string(),
- });
- }
- };
-
- // If we have both payloads `xyz.radicle.{project,crefs}` ensure that,
- // in the `crefs` payload there is no …
- // 1. … rule that matches the default branch from the `project` payload.
- // (This rule must be synthesized!)
- // 2. … symbolic reference with the name `HEAD`.
- // (This reference must be synthesized!)
- match crefs.zip(project) {
- Some((crefs, project)) => {
- let default = project.default_branch_qualified().to_owned();
- let matches = crefs
- .rules()
- .matches(&default)
- .map(|(pattern, _)| pattern.to_string())
- .collect::<Vec<_>>();
- if !matches.is_empty() {
- return Err(error::DocVerification::DisallowDefaultBranchRule { matches, default });
- }
-
- if let Some(symbolic) = crefs.symbolic().resolve_head() {
- return Err(error::DocVerification::DisallowDefaultBranchSymbolic {
- symbolic: symbolic.to_ref_string(),
- default,
- });
- }
- }
- _ => { /* we validate below */ }
+ if let Some(Err(PayloadError::Json(e))) = proposal.project() {
+ return Err(error::DocVerification::PayloadError {
+ id: PayloadId::project().clone(),
+ err: e.to_string(),
+ });
}
+ // Verify that the canonical references payload is valid. The default branch
+ // and its `HEAD` symbolic reference are now governed entirely by the
+ // `xyz.radicle.crefs` payload, which must be present and resolvable.
+ if let Err(e) = proposal.canonical_refs() {
+ return Err(error::DocVerification::PayloadError {
+ id: PayloadId::canonical_refs().clone(),
+ err: e.to_string(),
+ });
+ }
Ok(proposal)
}
@@ -264,12 +231,39 @@ fn verify_delegates(
proposal: &RawDoc,
repo: &storage::git::Repository,
) -> Result<Option<Vec<error::DelegateVerification>>, RepositoryError> {
- let dids = &proposal.delegates;
- let threshold = proposal.threshold;
+ use super::{CanonicalRefsError, Delegates, DocError, GetPayload as _};
+
let (canonical, _) = repo.canonical_head()?;
- let mut missing = Vec::with_capacity(dids.len());
+ // The quorum for the canonical default branch is defined by the canonical
+ // reference rule that matches it. Resolve the *validated* rule so that (a)
+ // the most specific matching rule is chosen (the raw rules are only byte
+ // ordered), and (b) both the required threshold and the population of
+ // voters counted below come from that same rule. Fail closed: an unreadable
+ // or invalid crefs payload, or a branch with no matching rule, is a
+ // verification error, not an assumed quorum of 1.
+ let delegates = Delegates::new(proposal.delegates().iter().copied()).map_err(DocError::from)?;
+ // Read the rules from the *migrated* document, so that a document stored at
+ // an older version is governed by the same rules its readers see.
+ let crefs = proposal
+ .view()
+ .map_err(DocError::from)?
+ .raw_canonical_refs()
+ .ok_or(CanonicalRefsError::Missing)?
+ .map_err(CanonicalRefsError::Payload)?
+ .try_into_canonical_refs(&mut || delegates.clone())
+ .map_err(CanonicalRefsError::from)?;
+ let (_, rule) = crefs
+ .rules()
+ .matches(&canonical)
+ .next()
+ .ok_or(RepositoryError::MissingBranchRule)?;
+ let allowed = rule.allowed();
+ let threshold = usize::from(*rule.threshold());
- for did in dids {
+ // Count the votes over the rule's `allowed` set, which may differ from the
+ // identity delegates when the default branch is governed by an explicit set.
+ let mut missing = Vec::with_capacity(allowed.len());
+ for did in allowed.iter() {
match refs::SignedRefs::load((*did).into(), repo)
.map_err(|err| storage::Error::Refs(storage::refs::Error::Read(err)))?
{
@@ -287,7 +281,7 @@ fn verify_delegates(
}
}
- Ok((dids.len() - missing.len() < threshold).then_some(missing))
+ Ok((allowed.len() - missing.len() < threshold).then_some(missing))
}
#[allow(clippy::unwrap_used)]
@@ -295,24 +289,33 @@ fn verify_delegates(
mod test {
use serde_json::json;
- use super::*;
+ use super::PayloadUpsert;
use crate::{
- identity::doc::{PayloadId, update::error},
- prelude::RawDoc,
+ identity::doc::{IDENTITY_VERSION, PayloadId, Version},
test::arbitrary,
};
- use super::PayloadUpsert;
+ /// A version-2 document, whose crefs payload alone governs the default
+ /// branch. These cases are about that payload, so the version is pinned.
+ fn v2() -> crate::prelude::RawDoc {
+ arbitrary::raw_doc_at(IDENTITY_VERSION)
+ }
#[test]
fn can_update_crefs() {
- let raw = arbitrary::r#gen::<RawDoc>(1);
+ // The document's default branch is `master`; keep its rule and add an
+ // unrelated tags rule.
+ let raw = v2();
let raw = super::payload(
raw,
[PayloadUpsert {
id: PayloadId::canonical_refs().clone(),
key: "rules".to_string(),
value: json!({
+ "refs/heads/master": {
+ "threshold": 1,
+ "allow": "delegates"
+ },
"refs/tags/*": {
"threshold": 1,
"allow": "delegates"
@@ -326,10 +329,10 @@ mod test {
}
#[test]
- fn cannot_include_default_branch_rule() {
- let raw = arbitrary::r#gen::<RawDoc>(1);
- let project = raw.project().unwrap().unwrap();
- let branch = project.default_branch_qualified();
+ fn default_branch_requires_rule() {
+ // A document whose `HEAD` symbolic reference has no matching rule is
+ // invalid, since the canonical head cannot be resolved.
+ let raw = v2();
let raw = super::payload(
raw,
[PayloadUpsert {
@@ -339,48 +342,77 @@ mod test {
"refs/tags/*": {
"threshold": 1,
"allow": "delegates"
- },
- branch.as_str(): {
- "threshold": 1,
- "allow": "delegates",
}
}),
}],
)
.unwrap();
assert!(
- matches!(
- super::verify(raw),
- Err(error::DocVerification::DisallowDefaultBranchRule { .. })
- ),
- "Verification should be rejected for including default branch rule"
- )
+ super::verify(raw).is_err(),
+ "Verification should fail when the default branch has no rule"
+ );
}
#[test]
- fn default_branch_rule_exists_after_verification() {
- let raw = arbitrary::r#gen::<RawDoc>(1);
- let project = raw.project().unwrap().unwrap();
- let branch = project.default_branch_qualified();
+ fn threshold_targets_most_specific_rule() {
+ // Two rules match `HEAD` (`refs/heads/master`): the exact branch rule
+ // and a broad glob. `*` (0x2A) sorts before `m` (0x6D), so the
+ // lexicographically-first rule is the glob. Updating the threshold must
+ // rewrite the exact branch rule that actually governs the quorum, not
+ // the glob.
+ use crate::identity::doc::GetPayload as _;
+
+ let raw = v2();
let raw = super::payload(
raw,
[PayloadUpsert {
id: PayloadId::canonical_refs().clone(),
key: "rules".to_string(),
value: json!({
- "refs/tags/*": {
- "threshold": 1,
- "allow": "delegates"
- }
+ "refs/heads/*": { "threshold": 1, "allow": "delegates" },
+ "refs/heads/master": { "threshold": 1, "allow": "delegates" }
}),
}],
)
.unwrap();
- let verified = super::verify(raw).unwrap();
- let crefs = verified.canonical_refs().unwrap();
- assert!(
- crefs.rules().matches(&branch).next().is_some(),
- "Default branch rule is missing!"
+ let raw = super::threshold(raw, 3);
+
+ let crefs = raw.raw_canonical_refs().unwrap().unwrap();
+ let threshold_of = |pattern: &str| {
+ crefs
+ .raw_rules()
+ .iter()
+ .find(|(p, _)| p.as_str() == pattern)
+ .map(|(_, rule)| *rule.threshold())
+ };
+ assert_eq!(
+ threshold_of("refs/heads/master"),
+ Some(3),
+ "the exact branch rule governing HEAD should be updated"
+ );
+ assert_eq!(
+ threshold_of("refs/heads/*"),
+ Some(1),
+ "the broad glob rule should be left untouched"
);
}
+
+ #[test]
+ fn threshold_writes_version_1_field() {
+ // A version-1 document keeps its quorum in the top-level `threshold`,
+ // so an ordinary edit must write there and leave the version alone.
+ let raw = arbitrary::raw_doc_at(Version::new(1).unwrap());
+ let raw = super::threshold(raw, 1);
+ let doc = super::verify(raw).unwrap();
+
+ assert_eq!(doc.version(), Version::new(1).unwrap());
+ // The migrated view carries the same quorum in the crefs rule.
+ let crefs = doc.canonical_refs().unwrap();
+ let (_, rule) = crefs
+ .rules()
+ .matches(&doc.default_branch().unwrap())
+ .next()
+ .unwrap();
+ assert_eq!(usize::from(*rule.threshold()), 1);
+ }
}
diff --git a/crates/radicle/src/identity/doc/update/error.rs b/crates/radicle/src/identity/doc/update/error.rs
index 31ffde52a9..1fdca4de91 100644
--- a/crates/radicle/src/identity/doc/update/error.rs
+++ b/crates/radicle/src/identity/doc/update/error.rs
@@ -1,6 +1,5 @@
use thiserror::Error;
-use crate::git;
use crate::git::fmt::RefString;
use crate::identity::{Did, DocError, doc::PayloadId};
@@ -28,20 +27,6 @@ pub enum DocVerification {
PayloadError { id: PayloadId, err: String },
#[error(transparent)]
Doc(#[from] DocError),
- #[error(
- "incompatible payloads: The rule(s) xyz.radicle.crefs.rules.{matches:?} matches the value of xyz.radicle.project.defaultBranch ('{default}'). Possible resolutions: Change the name of the default branch or remove the rule(s)."
- )]
- DisallowDefaultBranchRule {
- matches: Vec<String>,
- default: git::fmt::Qualified<'static>,
- },
- #[error(
- "incompatible payloads: The symbolic reference xyz.radicle.crefs.symbolic.HEAD → '{symbolic}' conflicts with xyz.radicle.project.defaultBranch ('{default}'). Possible resolutions: Remove either of the two."
- )]
- DisallowDefaultBranchSymbolic {
- symbolic: RefString,
- default: git::fmt::Qualified<'static>,
- },
}
#[derive(Clone, Debug)]
diff --git a/crates/radicle/src/identity/doc/v1.rs b/crates/radicle/src/identity/doc/v1.rs
new file mode 100644
index 0000000000..f7a8b56950
--- /dev/null
+++ b/crates/radicle/src/identity/doc/v1.rs
@@ -0,0 +1,60 @@
+//! The version-1 identity document.
+
+use std::collections::BTreeMap;
+
+use serde::{Deserialize, Serialize};
+
+use crate::git::fmt::RefString;
+use crate::identity::Did;
+
+use super::{Payload, PayloadId, Visibility};
+
+/// A version-1 identity document, in the shape it is stored in.
+///
+/// The default branch is the `defaultBranch` field of the `xyz.radicle.project`
+/// payload, and its write quorum is the top-level `threshold`. Released clients
+/// wrote no `version` key, so none is serialized here either.
+///
+/// [`Migrate`] moves both into the `xyz.radicle.crefs` payload.
+///
+/// [`Migrate`]: super::migrate::Migrate
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Doc {
+ /// The payload section.
+ pub payload: BTreeMap<PayloadId, Payload>,
+ /// The delegates section.
+ pub delegates: Vec<Did>,
+ /// The number of delegates required to accept a change to the default
+ /// branch.
+ pub threshold: usize,
+ /// Repository visibility.
+ #[serde(default, skip_serializing_if = "Visibility::is_public")]
+ pub visibility: Visibility,
+}
+
+impl Doc {
+ /// Read `defaultBranch` from the `xyz.radicle.project` payload.
+ ///
+ /// Returns `None` when the payload is absent, or when the field is missing
+ /// or is not a valid reference name. Version 1 accepted such a document as
+ /// long as the `xyz.radicle.crefs` payload defined `HEAD` itself.
+ pub fn default_branch(&self) -> Option<RefString> {
+ self.payload
+ .get(PayloadId::project())?
+ .get("defaultBranch")?
+ .as_str()
+ .and_then(|name| RefString::try_from(name).ok())
+ }
+
+ /// Remove `defaultBranch` from the `xyz.radicle.project` payload, if
+ /// present. Version 2 governs the default branch through
+ /// `xyz.radicle.crefs` alone.
+ pub(super) fn remove_default_branch(&mut self) {
+ if let Some(project) = self.payload.get_mut(PayloadId::project())
+ && let Some(object) = project.as_object_mut()
+ {
+ object.remove("defaultBranch");
+ }
+ }
+}
diff --git a/crates/radicle/src/identity/doc/v2.rs b/crates/radicle/src/identity/doc/v2.rs
new file mode 100644
index 0000000000..6662d627c9
--- /dev/null
+++ b/crates/radicle/src/identity/doc/v2.rs
@@ -0,0 +1,152 @@
+//! The version-2 identity document.
+
+use std::collections::BTreeMap;
+
+use serde::ser::SerializeStruct as _;
+use serde::{Deserialize, Serialize, Serializer};
+use serde_json as json;
+
+use crate::git;
+use crate::git::canonical::rules::{self, Rules};
+use crate::git::canonical::symbolic::{RawSymbolicRefs, SymbolicRefs};
+use crate::git::fmt::RefString;
+use crate::identity::Did;
+use crate::identity::crefs::RawCanonicalRefs;
+
+use super::{Delegates, GetPayload as _, IDENTITY_VERSION, Payload, PayloadId, Visibility};
+
+/// A version-2 identity document, in the shape it is stored in.
+///
+/// The `xyz.radicle.crefs` payload is the sole authority over the default
+/// branch and its write quorum: there is no top-level `threshold`, and the
+/// `xyz.radicle.project` payload carries no `defaultBranch`.
+#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Doc {
+ /// The payload section.
+ pub payload: BTreeMap<PayloadId, Payload>,
+ /// The delegates section.
+ pub delegates: Vec<Did>,
+ /// Repository visibility.
+ #[serde(default)]
+ pub visibility: Visibility,
+}
+
+impl Serialize for Doc {
+ fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+ // `version` is a constant of this schema rather than data, so it is
+ // written here instead of being held in a field. Version 1 documents
+ // must keep serializing without a `version` key, which is why the two
+ // schemas serialize separately.
+ let public = self.visibility.is_public();
+ let mut doc = serializer.serialize_struct("Doc", if public { 3 } else { 4 })?;
+
+ doc.serialize_field("version", &IDENTITY_VERSION)?;
+ doc.serialize_field("payload", &self.payload)?;
+ doc.serialize_field("delegates", &self.delegates)?;
+ if public {
+ doc.skip_field("visibility")?;
+ } else {
+ doc.serialize_field("visibility", &self.visibility)?;
+ }
+ doc.end()
+ }
+}
+
+impl Doc {
+ /// Check the invariants that distinguish this schema from version 1.
+ ///
+ /// The `xyz.radicle.project` payload must not carry a `defaultBranch`.
+ /// Without this check the field would merely be ignored, since [`Project`]
+ /// swallows unknown fields when deserializing.
+ ///
+ /// [`Project`]: crate::identity::Project
+ pub fn validate(&self) -> Result<(), DefaultBranchDisallowed> {
+ match self.payload.get(PayloadId::project()) {
+ Some(project) if project.get("defaultBranch").is_some() => Err(DefaultBranchDisallowed),
+ _ => Ok(()),
+ }
+ }
+
+ /// Set the write quorum of the default branch.
+ ///
+ /// The threshold lives in the `xyz.radicle.crefs` rule that matches the
+ /// target of the `HEAD` symbolic reference. This rewrites that rule's
+ /// threshold, preserving its `allow` value. If no such rule is present, the
+ /// document is left unchanged.
+ pub fn set_threshold(&mut self, threshold: usize) {
+ let mut crefs = self
+ .raw_canonical_refs()
+ .and_then(|crefs| crefs.ok())
+ .unwrap_or_default();
+
+ // `RawSymbolicRefs` cannot resolve a `HEAD` chain, so validate them
+ // first.
+ let symbolic = SymbolicRefs::try_from(crefs.symbolic().clone()).ok();
+ if let Some(head) = symbolic.as_ref().and_then(|symbolic| symbolic.resolve_head()) {
+ // Target the *most specific* rule matching `HEAD`, consistent with
+ // the enforcement paths (`Doc::canonical_refs`, patch merge,
+ // fetch). Because `RawRules` is keyed by plain byte order,
+ // `RawRules::matches().next()` could rewrite a broad glob (e.g.
+ // `refs/heads/*`) instead of the exact branch rule that actually
+ // governs the quorum. Resolving through validated `Rules` restores
+ // specificity ordering.
+ let pattern = Delegates::new(self.delegates.clone())
+ .ok()
+ .and_then(|delegates| {
+ Rules::from_raw(crefs.raw_rules().clone(), &mut || delegates.clone()).ok()
+ })
+ .and_then(|rules| rules.matches(head).next().map(|(p, _)| p.clone()));
+
+ if let Some(pattern) = pattern
+ && let Some(allow) = crefs
+ .raw_rules()
+ .rules
+ .get(&pattern)
+ .map(|rule| rule.allowed().clone())
+ {
+ crefs
+ .raw_rules_mut()
+ .insert(pattern, rules::Rule::new(allow, threshold));
+ }
+ }
+ let value = json::to_value(crefs).expect("v2::Doc::set_threshold: crefs are serializable");
+ self.payload
+ .insert(PayloadId::canonical_refs().clone(), Payload::from(value));
+ }
+}
+
+/// The `xyz.radicle.project` payload of a version-2 document defines
+/// `defaultBranch`, which version 2 does not allow.
+#[derive(Debug, thiserror::Error)]
+#[error(
+ "the `xyz.radicle.project` payload must not define `defaultBranch`; \
+ the default branch is governed by the `xyz.radicle.crefs` payload"
+)]
+pub struct DefaultBranchDisallowed;
+
+/// Build the `xyz.radicle.crefs` payload for a default branch governed by the
+/// delegates at the given `threshold`.
+///
+/// This produces a rule matching `refs/heads/<default_branch>` with an `allow`
+/// value of `delegates`, and a `HEAD` symbolic reference targeting that branch.
+pub fn default_branch_crefs(default_branch: &RefString, threshold: usize) -> Payload {
+ let mut raw_rules = rules::RawRules::default();
+ raw_rules.insert(
+ branch_pattern(default_branch),
+ rules::Rule::new(rules::Allowed::Delegates, threshold),
+ );
+ let symbolic = RawSymbolicRefs::from([(
+ git::fmt::refname!("HEAD"),
+ git::refs::branch(default_branch).to_ref_string(),
+ )]);
+ let crefs = RawCanonicalRefs::new(raw_rules, symbolic);
+ let value = json::to_value(crefs).expect("v2::default_branch_crefs: crefs are serializable");
+
+ Payload::from(value)
+}
+
+/// The rule pattern that matches exactly the given branch.
+pub(super) fn branch_pattern(branch: &RefString) -> git::fmt::refspec::QualifiedPattern<'static> {
+ git::fmt::refspec::QualifiedPattern::from(git::refs::branch(branch).to_owned())
+}
diff --git a/crates/radicle/src/identity/project.rs b/crates/radicle/src/identity/project.rs
index 308d8a4d77..92d34c72d7 100644
--- a/crates/radicle/src/identity/project.rs
+++ b/crates/radicle/src/identity/project.rs
@@ -7,8 +7,6 @@ use serde::{
use thiserror::Error;
use crate::crypto;
-use crate::git::BranchName;
-use crate::git::{fmt::Qualified, refs::branch};
use crate::identity::doc;
use crate::identity::doc::Payload;
@@ -21,8 +19,6 @@ pub enum ProjectError {
Name(&'static str),
#[error("invalid description: {0}")]
Description(&'static str),
- #[error("invalid default branch: {0}")]
- DefaultBranch(&'static str),
}
/// A valid project name.
@@ -99,8 +95,6 @@ pub struct Project {
name: ProjectName,
/// Project description.
description: String,
- /// Project default branch.
- default_branch: BranchName,
}
impl<'de> Deserialize<'de> for Project {
@@ -113,7 +107,6 @@ impl<'de> Deserialize<'de> for Project {
enum Field {
Name,
Description,
- DefaultBranch,
/// A catch-all variant to allow for unknown fields
Unknown(#[allow(dead_code)] String),
}
@@ -133,7 +126,6 @@ impl<'de> Deserialize<'de> for Project {
{
let mut name = None;
let mut description = None;
- let mut default_branch = None;
while let Some(key) = map.next_key()? {
match key {
@@ -149,21 +141,13 @@ impl<'de> Deserialize<'de> for Project {
}
description = Some(map.next_value()?);
}
- Field::DefaultBranch => {
- if default_branch.is_some() {
- return Err(de::Error::duplicate_field("defaultBranch"));
- }
- default_branch = Some(map.next_value()?);
- }
Field::Unknown(_) => continue,
}
}
let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
let description =
description.ok_or_else(|| de::Error::missing_field("description"))?;
- let default_branch =
- default_branch.ok_or_else(|| de::Error::missing_field("defaultBranch"))?;
- Project::new(name, description, default_branch).map_err(|errs| {
+ Project::new(name, description).map_err(|errs| {
de::Error::custom(
errs.into_iter()
.map(|err| err.to_string())
@@ -173,7 +157,7 @@ impl<'de> Deserialize<'de> for Project {
})
}
}
- const FIELDS: &[&str] = &["name", "description", "defaultBranch"];
+ const FIELDS: &[&str] = &["name", "description"];
deserializer.deserialize_struct("Project", FIELDS, ProjectVisitor)
}
}
@@ -187,12 +171,7 @@ impl Project {
///
/// * `name`'s length must not be empty and must not exceed 255.
/// * `description`'s length must not exceed 255.
- /// * `default_branch`'s length must not be empty and must not exceed 255.
- pub fn new(
- name: ProjectName,
- description: String,
- default_branch: BranchName,
- ) -> Result<Self, Vec<ProjectError>> {
+ pub fn new(name: ProjectName, description: String) -> Result<Self, Vec<ProjectError>> {
let mut errs = Vec::new();
if description.len() > doc::MAX_STRING_LENGTH {
@@ -201,22 +180,8 @@ impl Project {
));
}
- if default_branch.is_empty() {
- errs.push(ProjectError::DefaultBranch(
- "default branch cannot be empty",
- ))
- } else if default_branch.len() > doc::MAX_STRING_LENGTH {
- errs.push(ProjectError::DefaultBranch(
- "default branch cannot exceed 255 bytes",
- ))
- }
-
if errs.is_empty() {
- Ok(Self {
- name,
- description,
- default_branch,
- })
+ Ok(Self { name, description })
} else {
Err(errs)
}
@@ -233,12 +198,10 @@ impl Project {
self,
name: impl Into<Option<ProjectName>>,
description: impl Into<Option<String>>,
- default_branch: impl Into<Option<BranchName>>,
) -> Result<Self, Vec<ProjectError>> {
let name = name.into().unwrap_or(self.name);
let description = description.into().unwrap_or(self.description);
- let default_branch = default_branch.into().unwrap_or(self.default_branch);
- Self::new(name, description, default_branch)
+ Self::new(name, description)
}
#[inline]
@@ -250,21 +213,6 @@ impl Project {
pub fn description(&self) -> &str {
&self.description
}
-
- /// Return the default branch of the project.
- ///
- /// To obtain the default branch of the repository, prefer
- /// [`super::Doc::default_branch_name`].
- #[inline]
- pub fn default_branch(&self) -> &BranchName {
- &self.default_branch
- }
-
- /// Return the qualified name of the default branch.
- #[inline]
- pub fn default_branch_qualified(&self) -> Qualified<'_> {
- branch(&self.default_branch)
- }
}
impl From<Project> for Payload {
diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs
index b8644af311..98360800c6 100644
--- a/crates/radicle/src/rad.rs
+++ b/crates/radicle/src/rad.rs
@@ -44,7 +44,8 @@ pub enum InitError {
Storage(#[from] storage::Error),
}
-/// Initialize a new Radicle project from a git repository.
+/// Initialize a new Radicle project from a git repository, at the current
+/// identity document version.
pub fn init(
repo: &git::raw::Repository,
name: ProjectName,
@@ -53,15 +54,37 @@ pub fn init(
visibility: Visibility,
signer: &impl crypto::Signer,
storage: &impl WriteStorage,
+) -> Result<(RepoId, identity::Doc, SignedRefs), InitError> {
+ init_at(
+ doc::IDENTITY_VERSION,
+ repo,
+ name,
+ description,
+ default_branch,
+ visibility,
+ signer,
+ storage,
+ )
+}
+
+/// Like [`init`], but writing the identity document at the given `version`.
+///
+/// Initializing at an older version keeps the repository readable to releases
+/// that predate [`doc::IDENTITY_VERSION`], until `rad id migrate` is run.
+#[allow(clippy::too_many_arguments)]
+pub fn init_at(
+ version: doc::Version,
+ repo: &git::raw::Repository,
+ name: ProjectName,
+ description: &str,
+ default_branch: BranchName,
+ visibility: Visibility,
+ signer: &impl crypto::Signer,
+ storage: &impl WriteStorage,
) -> Result<(RepoId, identity::Doc, SignedRefs), InitError> {
// TODO: Better error when project id already exists in storage, but remote doesn't.
let delegate: identity::Did = signer.public_key().into();
- let proj = Project::new(
- name.to_owned(),
- description.to_owned(),
- default_branch.clone(),
- )
- .map_err(|errs| {
+ let proj = Project::new(name.to_owned(), description.to_owned()).map_err(|errs| {
InitError::ProjectPayload(
errs.into_iter()
.map(|err| err.to_string())
@@ -69,7 +92,7 @@ pub fn init(
.join(", "),
)
})?;
- let doc = identity::Doc::initial(proj, delegate, visibility);
+ let doc = identity::Doc::initial_at(version, proj, delegate, &default_branch, visibility)?;
let (project, identity) = Repository::init(&doc, storage, signer)?;
let url = git::Url::from(project.id);
@@ -173,16 +196,11 @@ pub fn fork_remote(
// refs/namespaces/<pk>/refs/tags/*
let me = signer.public_key();
- let doc = storage.get(proj)?.ok_or(ForkError::NotFound(proj))?;
let repository = storage.repository_mut(proj)?;
+ let default_branch = git::refs::branch(&repository.default_branch_name()?);
let raw = repository.raw();
-
- #[allow(clippy::unwrap_used)]
- let default_branch = doc.default_branch().unwrap();
-
let remote_head = raw.refname_to_id(default_branch.with_namespace(remote.into()).as_str())?;
-
raw.reference(
&default_branch.with_namespace(me.into()),
remote_head,
@@ -564,7 +582,7 @@ mod tests {
assert_eq!(remotes[public_key].refs.refs(), refs.refs());
assert_eq!(project.name(), "acme");
assert_eq!(project.description(), "Acme's repo");
- assert_eq!(project.default_branch(), &git::fmt::refname!("master"));
+ assert_eq!(doc.default_branch().unwrap().as_str(), "refs/heads/master");
assert_eq!(doc.delegates().first(), &Did::from(public_key));
}
diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs
index 09c8ac3def..4b88f0f7e0 100644
--- a/crates/radicle/src/storage.rs
+++ b/crates/radicle/src/storage.rs
@@ -527,6 +527,12 @@ pub trait ReadRepository: Sized + ValidateRepository {
Ok(self.identity_doc()?.default_branch()?.to_owned())
}
+ /// Gets the short name of the default branch of self, according to the
+ /// canonical references payload in the identity document.
+ fn default_branch_name(&self) -> Result<crate::git::fmt::RefString, RepositoryError> {
+ Ok(self.identity_doc()?.default_branch_name()?)
+ }
+
/// Compute the canonical head of this repository.
///
/// Ignores any existing `HEAD` reference.
diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs
index 51b00402a9..6029f4aec5 100644
--- a/crates/radicle/src/storage/refs.rs
+++ b/crates/radicle/src/storage/refs.rs
@@ -565,12 +565,12 @@ mod tests {
{
let paris_doc = paris_doc
.with_edits(|doc| {
- doc.delegates.push(bob.public_key().into());
+ doc.delegates_mut().push(bob.public_key().into());
})
.unwrap();
let london_doc = london_doc
.with_edits(|doc| {
- doc.delegates.push(bob.public_key().into());
+ doc.delegates_mut().push(bob.public_key().into());
})
.unwrap();
diff --git a/crates/radicle/src/test/arbitrary.rs b/crates/radicle/src/test/arbitrary.rs
index ce81c2397e..9357cb814c 100644
--- a/crates/radicle/src/test/arbitrary.rs
+++ b/crates/radicle/src/test/arbitrary.rs
@@ -15,7 +15,7 @@ use crate::identity::doc::Visibility;
use crate::identity::project::ProjectName;
use crate::identity::{
Did,
- doc::{Doc, DocAt, RawDoc, RepoId},
+ doc::{Doc, DocAt, IDENTITY_VERSION, RawDoc, RepoId, Version},
project::Project,
};
use crate::node::address::{AddressType, Source};
@@ -140,13 +140,8 @@ impl Arbitrary for Project {
let description = iter::repeat_with(|| rng.alphanumeric())
.take(length * 2)
.collect();
- let default_branch: git::fmt::RefString = iter::repeat_with(|| rng.alphanumeric())
- .take(length)
- .collect::<String>()
- .try_into()
- .unwrap();
- Project::new(name, description, default_branch).unwrap()
+ Project::new(name, description).unwrap()
}
}
@@ -162,13 +157,43 @@ impl Arbitrary for Visibility {
}
}
+/// An arbitrary stored document version, so that generated documents exercise
+/// both the version-1 and the version-2 path.
+fn identity_version(g: &mut qcheck::Gen) -> Version {
+ if bool::arbitrary(g) {
+ #[allow(clippy::unwrap_used)]
+ Version::new(1).unwrap()
+ } else {
+ IDENTITY_VERSION
+ }
+}
+
+/// An arbitrary [`RawDoc`] stored at the given `version`.
+pub fn raw_doc_at(version: Version) -> RawDoc {
+ RawDoc::new_at(
+ version,
+ r#gen::<Project>(1),
+ vec![r#gen::<Did>(1)],
+ &git::fmt::refname!("master"),
+ 1,
+ Visibility::Public,
+ )
+}
+
impl Arbitrary for RawDoc {
fn arbitrary(g: &mut qcheck::Gen) -> Self {
let proj = Project::arbitrary(g);
let delegate = Did::arbitrary(g);
let visibility = Visibility::arbitrary(g);
- Self::new(proj, vec![delegate], 1, visibility)
+ Self::new_at(
+ identity_version(g),
+ proj,
+ vec![delegate],
+ &git::fmt::refname!("master"),
+ 1,
+ visibility,
+ )
}
}
@@ -178,8 +203,16 @@ impl Arbitrary for Doc {
let delegates = vec_distinct::<Did>(1..6);
let threshold = delegates.len() / 2 + 1;
let visibility = Visibility::arbitrary(g);
- let doc = RawDoc::new(project, delegates, threshold, visibility);
+ let doc = RawDoc::new_at(
+ identity_version(g),
+ project,
+ delegates,
+ &git::fmt::refname!("master"),
+ threshold,
+ visibility,
+ );
+ #[allow(clippy::unwrap_used)]
doc.verified().unwrap()
}
}
diff --git a/rad-id.1.adoc b/rad-id.1.adoc
index 173d91e29c..49e508c9f7 100644
--- a/rad-id.1.adoc
+++ b/rad-id.1.adoc
@@ -15,6 +15,7 @@ rad-id - Manage changes to a Radicle repository's identity.
*rad id* [<option>...] +
*rad id* _list_ [<option>...] +
*rad id* _update_ [--title <string>] [--description <string>] <option>... +
+*rad id* _migrate_ [--title <string>] [--description <string>] [<option>...] +
*rad id* _edit_ <revision-id> [--title <string>] [--description <string>] [<option>...] +
*rad id* _show_ <revision-id> [<option>...] +
*rad id* _accept_ | _reject_ <revision-id> [<option>...] +
@@ -89,6 +90,26 @@ automatically accepted and included into the identity document.
*--edit*::
Opens your $EDITOR to edit the JSON contents directly.
+=== migrate
+
+Proposes a revision that migrates the identity document to the current version.
+
+An identity document written by an older release keeps its stored version. It is
+migrated to the current version in memory each time it is read, so a reader
+always sees the current shape, but the document on disk does not change. This
+command writes the migration down, as an ordinary revision that the delegates
+vote on.
+
+Once the migration is adopted, the repository is no longer readable to releases
+that predate the new version. The command fails if the document is already at
+the current version.
+
+*--title* _<string>_::
+ Set the title for the new revision.
+
+*--description* _<string>_::
+ Set the description for the new revision.
+
=== edit
Edit an existing revision to the identity document. The revision must still be
commit 7a77ba481c65cc3efcbe5c660ef8dc2997ae6ce8
Author: Daniel Norman <daniel@norman.life>
Date: Mon Aug 17 15:12:18 2026 +0200
patch: Use cref rule quorum for merge tally
To determine whether a patch has been merged to the default branch, we
tally merges based on the default branch quorum: allow set and
threshold. With the introduction of custom branch, the tallying wasn't
updated to use the quorum rules for the target branch, instead merging
on the identity document threshold and delegate set.
This fix uses the `allow` set and the `threshold` of the most specific
rule that matches the target branch of patch.
Note that a reference that no rule matches never becomes canonical, so a
patch that targets one can never reach a quorum.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76f0731c3d..675a94bcab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## Unreleased
+
+## Fixes
+
+- A patch now merges on the quorum of the canonical reference rule that
+ matches its target branch, not on the identity document threshold.
+ Only merges by DIDs in the rule's `allow` set count, and they must
+ reach the rule's `threshold`. A patch that targets a branch which no
+ rule matches cannot merge.
+
## 1.10.3 - 2026-09-07
### Fixes
diff --git a/crates/radicle/src/cob/patch.rs b/crates/radicle/src/cob/patch.rs
index 7b83ca4cf3..8016b63927 100644
--- a/crates/radicle/src/cob/patch.rs
+++ b/crates/radicle/src/cob/patch.rs
@@ -1250,7 +1250,7 @@ impl Patch {
return Ok(());
};
- let expected_branch = self.merge_target_branch(identity)?;
+ let expected_branch = self.merge_target_branch(identity)?.to_owned();
// Nb. We don't return an error in case the merge commit is not an
// ancestor of the default branch. The default branch can change
@@ -1274,15 +1274,33 @@ impl Patch {
},
);
+ // The quorum for the target branch is defined by the canonical
+ // reference rule that matches it: only merges made by an allowed
+ // DID count, and the rule's threshold must be reached.
+ //
+ // A branch that no rule matches never becomes a canonical
+ // reference, so a patch targeting it can never reach a quorum.
+ //
+ // As above, a merge we cannot evaluate is skipped rather
+ // than rejected.
+ let Ok(crefs) = identity.canonical_refs() else {
+ return Ok(());
+ };
+ let Some((_, rule)) = crefs.rules().matches(&expected_branch).next() else {
+ return Ok(());
+ };
+
let mut merges = self.merges.iter().fold(
HashMap::<(RevisionId, git::Oid), usize>::new(),
- |mut acc, (_, merge)| {
- *acc.entry((merge.revision, merge.commit)).or_default() += 1;
+ |mut acc, (actor, merge)| {
+ if rule.allowed().contains(&Did::from(*actor)) {
+ *acc.entry((merge.revision, merge.commit)).or_default() += 1;
+ }
acc
},
);
- // Discard revisions that weren't merged by a threshold of delegates.
- merges.retain(|_, count| *count >= identity.threshold());
+ // Discard revisions that weren't merged by a threshold of allowed DIDs.
+ merges.retain(|_, count| *count >= usize::from(*rule.threshold()));
match merges.into_keys().collect::<Vec<_>>().as_slice() {
[] => {
@@ -3370,6 +3388,274 @@ mod test {
);
}
+ /// Build a patch targeting `refs/heads/accepted`, together with the
+ /// document and repository needed to apply merges to it.
+ ///
+ /// The document has four delegates and a threshold of three, while the
+ /// rule matching the target branch allows only Alice and Bob, with a
+ /// threshold of two. The two quorums are distinguishable.
+ fn merge_quorum_fixture(
+ signers: &[&SigningKey],
+ commit: git::Oid,
+ ) -> (Patch, Doc, MockRepository, RevisionId) {
+ let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
+ let [alice, bob, eve, dave] = signers else {
+ panic!("merge_quorum_fixture: expected four signers");
+ };
+
+ let mut raw_doc = RawDoc::new(
+ r#gen::<Project>(1),
+ vec![alice.did(), bob.did(), eve.did(), dave.did()],
+ 3,
+ identity::Visibility::Public,
+ );
+ let crefs = serde_json::json!({
+ "rules": {
+ "refs/heads/accepted": {
+ "allow": [alice.did(), bob.did()],
+ "threshold": 2
+ }
+ }
+ });
+ raw_doc.payload.insert(
+ identity::doc::PayloadId::canonical_refs().clone(),
+ identity::doc::Payload::from(crefs),
+ );
+ let doc = raw_doc.verified().unwrap();
+
+ // Every signer publishes the merge commit on the target branch, so that
+ // the merge is not skipped for being unreachable.
+ let branch = git::fmt::qualified!("refs/heads/accepted");
+ let mut repo = MockRepository::new(r#gen::<RepoId>(1), doc.clone());
+ for signer in signers {
+ let mut refs = crate::storage::refs::Refs::new();
+ refs.insert(branch.to_ref_string(), commit);
+ repo.remotes.insert(
+ *signer.public_key(),
+ crate::storage::refs::arbitrary::signed_refs(refs, commit, *signer),
+ );
+ }
+
+ let revision_id = RevisionId(arbitrary::entry_id());
+ let patch = Patch::new(
+ cob::Title::new("My Patch").unwrap(),
+ MergeTarget::Branch(TargetBranch::try_from("accepted").unwrap()),
+ (
+ revision_id,
+ Revision::new(
+ revision_id,
+ Author::new(alice.did()),
+ String::new(),
+ base,
+ commit,
+ env::local_time().into(),
+ Default::default(),
+ ),
+ ),
+ );
+
+ (patch, doc, repo, revision_id)
+ }
+
+ fn apply_merge(
+ patch: &mut Patch,
+ doc: &Doc,
+ repo: &MockRepository,
+ revision: RevisionId,
+ commit: git::Oid,
+ signer: &SigningKey,
+ ) {
+ patch
+ .action(
+ Action::Merge { revision, commit },
+ arbitrary::entry_id(),
+ *signer.public_key(),
+ env::local_time().into(),
+ &[],
+ doc,
+ repo,
+ )
+ .unwrap();
+ }
+
+ #[test]
+ fn test_patch_merge_quorum_uses_rule_threshold() {
+ let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
+ let alice = SigningKey::mock(14);
+ let bob = SigningKey::mock(23);
+ let eve = SigningKey::mock(31);
+ let dave = SigningKey::mock(42);
+ let signers = [&alice, &bob, &eve, &dave];
+
+ let (mut patch, doc, repo, revision) = merge_quorum_fixture(&signers, commit);
+
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &alice);
+ assert!(
+ !patch.is_merged(),
+ "one of two allowed merges is not a quorum"
+ );
+
+ // Two allowed merges reach the rule's threshold, even though the
+ // document threshold of three is not met.
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &bob);
+ assert_eq!(
+ *patch.state(),
+ State::Merged { revision, commit },
+ "the rule's threshold of two is reached"
+ );
+ }
+
+ #[test]
+ fn test_patch_merge_quorum_ignores_disallowed_merges() {
+ let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
+ let alice = SigningKey::mock(14);
+ let bob = SigningKey::mock(23);
+ let eve = SigningKey::mock(31);
+ let dave = SigningKey::mock(42);
+ let signers = [&alice, &bob, &eve, &dave];
+
+ let (mut patch, doc, repo, revision) = merge_quorum_fixture(&signers, commit);
+
+ // Eve and Dave are delegates, but the rule does not allow them, so
+ // their merges never count towards the quorum.
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &eve);
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &dave);
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &alice);
+
+ assert_eq!(patch.merges.len(), 3, "all three merges are recorded");
+ assert!(
+ !patch.is_merged(),
+ "only Alice's merge counts, which is below the rule's threshold"
+ );
+ }
+
+ #[test]
+ fn test_patch_merge_quorum_without_matching_rule() {
+ let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
+ let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
+ let alice = SigningKey::mock(14);
+
+ // The only rule is the one synthesized for the default branch, so
+ // nothing matches `refs/heads/staging`.
+ let project = Project::new(
+ ProjectName::from_str("unruled").unwrap(),
+ String::new(),
+ BranchName::from(git::fmt::RefString::try_from("master").unwrap()),
+ )
+ .unwrap();
+ let doc = RawDoc::new(project, vec![alice.did()], 1, identity::Visibility::Public)
+ .verified()
+ .unwrap();
+
+ let branch = git::fmt::qualified!("refs/heads/staging");
+ let mut repo = MockRepository::new(r#gen::<RepoId>(1), doc.clone());
+ let mut refs = crate::storage::refs::Refs::new();
+ refs.insert(branch.to_ref_string(), commit);
+ repo.remotes.insert(
+ *alice.public_key(),
+ crate::storage::refs::arbitrary::signed_refs(refs, commit, &alice),
+ );
+
+ let revision = RevisionId(arbitrary::entry_id());
+ let mut patch = Patch::new(
+ cob::Title::new("My Patch").unwrap(),
+ MergeTarget::Branch(TargetBranch::try_from("staging").unwrap()),
+ (
+ revision,
+ Revision::new(
+ revision,
+ Author::new(alice.did()),
+ String::new(),
+ base,
+ commit,
+ env::local_time().into(),
+ Default::default(),
+ ),
+ ),
+ );
+
+ // Alice is the only delegate, so she meets the document threshold on
+ // her own, but no rule makes `refs/heads/staging` canonical.
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &alice);
+
+ assert_eq!(patch.merges.len(), 1, "the merge is recorded");
+ assert!(
+ !patch.is_merged(),
+ "a branch that no rule matches can never reach a quorum"
+ );
+ }
+
+ /// The default branch keeps the quorum it had before rules were consulted.
+ ///
+ /// Without a `xyz.radicle.crefs` payload, the rule for the default branch
+ /// is synthesized as `delegates` at the document threshold, so the tally
+ /// must behave exactly as it did when it used the document directly.
+ #[test]
+ fn test_patch_merge_quorum_of_default_branch() {
+ let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
+ let commit = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
+ let alice = SigningKey::mock(14);
+ let bob = SigningKey::mock(23);
+ let eve = SigningKey::mock(31);
+
+ let project = Project::new(
+ ProjectName::from_str("unruled").unwrap(),
+ String::new(),
+ BranchName::from(git::fmt::RefString::try_from("master").unwrap()),
+ )
+ .unwrap();
+ let doc = RawDoc::new(
+ project,
+ vec![alice.did(), bob.did(), eve.did()],
+ 2,
+ identity::Visibility::Public,
+ )
+ .verified()
+ .unwrap();
+
+ let branch = git::fmt::qualified!("refs/heads/master");
+ let mut repo = MockRepository::new(r#gen::<RepoId>(1), doc.clone());
+ for signer in [&alice, &bob, &eve] {
+ let mut refs = crate::storage::refs::Refs::new();
+ refs.insert(branch.to_ref_string(), commit);
+ repo.remotes.insert(
+ *signer.public_key(),
+ crate::storage::refs::arbitrary::signed_refs(refs, commit, signer),
+ );
+ }
+
+ let revision = RevisionId(arbitrary::entry_id());
+ let mut patch = Patch::new(
+ cob::Title::new("My Patch").unwrap(),
+ MergeTarget::Delegates,
+ (
+ revision,
+ Revision::new(
+ revision,
+ Author::new(alice.did()),
+ String::new(),
+ base,
+ commit,
+ env::local_time().into(),
+ Default::default(),
+ ),
+ ),
+ );
+
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &alice);
+ assert!(
+ !patch.is_merged(),
+ "one of three delegates is below the document threshold"
+ );
+
+ apply_merge(&mut patch, &doc, &repo, revision, commit, &bob);
+ assert_eq!(
+ *patch.state(),
+ State::Merged { revision, commit },
+ "the synthesized rule resolves to the document threshold of two"
+ );
+ }
+
#[test]
fn json_serialization() {
let edit = Action::Label {
diff --git a/crates/radicle/src/storage/refs/arbitrary.rs b/crates/radicle/src/storage/refs/arbitrary.rs
index 67f07d0de0..e137a09b66 100644
--- a/crates/radicle/src/storage/refs/arbitrary.rs
+++ b/crates/radicle/src/storage/refs/arbitrary.rs
@@ -27,6 +27,19 @@ pub fn signed_refs_at(g: &mut qcheck::Gen, root: Oid, signer: &impl crypto::Sign
}
}
+/// Sign an exact set of `refs`, for tests that need specific reference names.
+pub fn signed_refs(refs: Refs, at: Oid, signer: &impl crypto::Signer) -> SignedRefs {
+ let signature = crypto::signature::Signer::sign(signer, &refs.canonical());
+ SignedRefs {
+ refs,
+ signature,
+ id: *signer.public_key(),
+ level: FeatureLevel::default(),
+ parent: None,
+ at,
+ }
+}
+
impl Arbitrary for Refs {
fn arbitrary(g: &mut qcheck::Gen) -> Self {
let names = &[
commit 0e5a56f25f51d07290613a9363bd8c0c9fc8e0be
Author: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
Date: Thu Sep 10 10:13:51 2026 +0200
protocol: Limit allocations when decoding frames
`VarInt` can get large enough to exhaust available memory on many
machines. Instead of allocating directly, check the size of the
allocation against some limit.
The limit chosen for frames is 128 KiB, which is roughly twice as much
as actual gossip and Git protocol frames are expected to be. However,
128 KiB is arguably short enough to not burden a standard consumer
machine too much.
diff --git a/crates/radicle-protocol/src/deserializer.rs b/crates/radicle-protocol/src/deserializer.rs
index 90575c7119..9b9c755a97 100644
--- a/crates/radicle-protocol/src/deserializer.rs
+++ b/crates/radicle-protocol/src/deserializer.rs
@@ -58,7 +58,18 @@ impl<const B: usize, D: wire::Decode> Deserializer<B, D> {
Ok(Some(msg))
}
- Err(wire::Error::UnexpectedEnd { .. }) => Ok(None),
+ Err(wire::Error::UnexpectedEnd { .. }) => {
+ log::debug!("Dropping incomplete frame: Expected more bytes.");
+ Ok(None)
+ }
+ Err(wire::Error::FrameTooLong { length, limit }) => {
+ log::debug!(
+ "Dropping frame that is too large: Expected at most {} bytes, got {} bytes.",
+ limit,
+ length
+ );
+ Ok(None)
+ }
Err(wire::Error::Invalid(err)) => Err(err),
}
}
diff --git a/crates/radicle-protocol/src/wire.rs b/crates/radicle-protocol/src/wire.rs
index 232755f085..ffde936001 100644
--- a/crates/radicle-protocol/src/wire.rs
+++ b/crates/radicle-protocol/src/wire.rs
@@ -93,6 +93,9 @@ pub enum Error {
#[error(transparent)]
Invalid(#[from] Invalid),
+ #[error("frame too long: expected at most {limit}, got {length}")]
+ FrameTooLong { length: usize, limit: usize },
+
#[error(
"unexpected end of buffer, requested {requested} more bytes but only {available} are available"
)]
@@ -147,7 +150,7 @@ pub trait Decode: Sized {
}
Ok(value)
}
- Err(err @ Error::UnexpectedEnd { .. }) => {
+ Err(err @ (Error::UnexpectedEnd { .. } | Error::FrameTooLong { .. })) => {
panic!("{}", err);
}
Err(Error::Invalid(e)) => Err(e),
diff --git a/crates/radicle-protocol/src/wire/frame.rs b/crates/radicle-protocol/src/wire/frame.rs
index 50c90dd999..5972cd72a3 100644
--- a/crates/radicle-protocol/src/wire/frame.rs
+++ b/crates/radicle-protocol/src/wire/frame.rs
@@ -210,6 +210,9 @@ pub struct Frame<M = Message> {
}
impl<M> Frame<M> {
+ /// The maximum length of a frame, in bytes (128 KiB).
+ pub const LENGTH_LIMIT: usize = 1 << 17;
+
/// Create a 'git' protocol frame.
pub fn git(stream: StreamId, data: Vec<u8>) -> Self {
Self {
@@ -360,7 +363,7 @@ impl<M: wire::Decode> wire::Decode for Frame<M> {
Ok(frame)
}
Ok(StreamType::Gossip) => {
- let data = varint::payload::decode(buf)?;
+ let data = varint::payload::decode(buf, Frame::<M>::LENGTH_LIMIT)?;
let mut cursor = io::Cursor::new(data);
let msg = M::decode(&mut cursor)?;
let frame = Frame {
@@ -375,7 +378,7 @@ impl<M: wire::Decode> wire::Decode for Frame<M> {
Ok(frame)
}
Ok(StreamType::Git) => {
- let data = varint::payload::decode(buf)?;
+ let data = varint::payload::decode(buf, Frame::<M>::LENGTH_LIMIT)?;
Ok(Frame::git(stream, data))
}
Err(n) => Err(wire::Invalid::StreamType { actual: n }.into()),
diff --git a/crates/radicle-protocol/src/wire/varint.rs b/crates/radicle-protocol/src/wire/varint.rs
index 884f5efa48..a2ef22fb54 100644
--- a/crates/radicle-protocol/src/wire/varint.rs
+++ b/crates/radicle-protocol/src/wire/varint.rs
@@ -163,10 +163,21 @@ pub mod payload {
buf.put_slice(payload);
}
- /// Decode varint-prefixed data payload.
- pub fn decode(buf: &mut impl Buf) -> Result<Vec<u8>, wire::Error> {
+ /// Decode varint-prefixed data payload, if the size of the payload
+ /// is at most `limit` bytes.
+ pub fn decode(buf: &mut impl Buf, limit: usize) -> Result<Vec<u8>, wire::Error> {
let size = VarInt::decode(buf)?;
- let mut data = vec![0; *size as usize];
+
+ let size = *size as usize;
+
+ if size > limit {
+ return Err(wire::Error::FrameTooLong {
+ length: size,
+ limit,
+ });
+ }
+
+ let mut data = vec![0; size];
buf.try_copy_to_slice(&mut data[..])?;
Ok(data)
commit d8298a1d4cca9f15b45dafdea98dd1a33823a4cf
Author: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
Date: Tue Sep 8 14:41:22 2026 +0200
treewide: Remove `test_` prefix from test `fn`s
This redundancy does not add much. These functions are already marked
via `#[test]`, and often times they are in a separate module named
"test" or "tests".
diff --git a/crates/radicle-cli-test/src/lib.rs b/crates/radicle-cli-test/src/lib.rs
index 095b9d8458..7a32e93022 100644
--- a/crates/radicle-cli-test/src/lib.rs
+++ b/crates/radicle-cli-test/src/lib.rs
@@ -576,7 +576,7 @@ mod tests {
use pretty_assertions::assert_eq;
#[test]
- fn test_parse() {
+ fn parse() {
let input = r#"
Let's try to track @dave and @sean:
``` RAD_HINT=true
@@ -664,7 +664,7 @@ $ rad sync
}
#[test]
- fn test_run() {
+ fn run() {
let input = r#"
Running a simple command such as `head`:
```
@@ -688,7 +688,7 @@ name = "radicle-cli-test"
}
#[test]
- fn test_example_spaced_brackets() {
+ fn example_spaced_brackets() {
let input = r#"
Running a simple command such as `head`:
```
diff --git a/crates/radicle-cli/src/commands/inspect.rs b/crates/radicle-cli/src/commands/inspect.rs
index 6cd54677ff..977730078d 100644
--- a/crates/radicle-cli/src/commands/inspect.rs
+++ b/crates/radicle-cli/src/commands/inspect.rs
@@ -309,10 +309,9 @@ fn tree(mut refs: Vec<String>) -> String {
#[cfg(test)]
mod test {
- use super::*;
#[test]
- fn test_tree() {
+ fn tree() {
let arg = vec![
String::from("z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/refs/heads/master"),
String::from("z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi/refs/rad/id"),
@@ -329,7 +328,7 @@ z6MknSLrJoTcukLrE435hVNQT4JUhbvWLX4kUzqkEStBU8Vi
"#
.trim_start();
- assert_eq!(tree(arg), exp);
- assert_eq!(tree(vec![String::new()]), "\n");
+ assert_eq!(super::tree(arg), exp);
+ assert_eq!(super::tree(vec![String::new()]), "\n");
}
}
diff --git a/crates/radicle-cli/src/commands/patch/review/builder.rs b/crates/radicle-cli/src/commands/patch/review/builder.rs
index 4b48d26689..f2815c6f55 100644
--- a/crates/radicle-cli/src/commands/patch/review/builder.rs
+++ b/crates/radicle-cli/src/commands/patch/review/builder.rs
@@ -964,7 +964,7 @@ mod tests {
use super::*;
#[test]
- fn test_review_comments_basic() {
+ fn review_comments_basic() {
let input = r#"
> @@ -2559,18 +2560,18 @@ where
> // Only consider onion addresses if configured.
@@ -1081,7 +1081,7 @@ Comment #5.
}
#[test]
- fn test_review_comments_multiline() {
+ fn review_comments_multiline() {
let input = r#"
> @@ -2559,9 +2560,7 @@ where
> // Only consider onion addresses if configured.
@@ -1176,7 +1176,7 @@ Woof.
}
#[test]
- fn test_review_comments_before() {
+ fn review_comments_before() {
let input = r#"
This is a top-level comment.
@@ -1228,7 +1228,7 @@ This is a top-level comment.
}
#[test]
- fn test_review_comments_split_hunk() {
+ fn review_comments_split_hunk() {
let input = r#"
> @@ -2559,6 +2560,4 @@ where
> // Only consider onion addresses if configured.
diff --git a/crates/radicle-cli/src/git.rs b/crates/radicle-cli/src/git.rs
index a476a3a24f..a3aaccc9a6 100644
--- a/crates/radicle-cli/src/git.rs
+++ b/crates/radicle-cli/src/git.rs
@@ -469,7 +469,7 @@ mod test {
use std::str::FromStr;
#[test]
- fn test_version_ord() {
+ fn version_ord() {
assert!(
Version {
major: 2,
@@ -495,7 +495,7 @@ mod test {
}
#[test]
- fn test_version_from_str() {
+ fn version_from_str() {
assert_eq!(
Version::from_str("git version 2.34.1\n").ok(),
Some(Version {
diff --git a/crates/radicle-cli/src/git/pretty_diff.rs b/crates/radicle-cli/src/git/pretty_diff.rs
index 53bb7052cd..f5bdf5a20d 100644
--- a/crates/radicle-cli/src/git/pretty_diff.rs
+++ b/crates/radicle-cli/src/git/pretty_diff.rs
@@ -600,7 +600,7 @@ mod test {
#[test]
#[ignore]
- fn test_pretty() {
+ fn pretty() {
let repo = Repository::open_ext::<_, _, &[&OsStr]>(
env!("CARGO_MANIFEST_DIR"),
RepositoryOpenFlags::all(),
diff --git a/crates/radicle-cli/src/git/unified_diff.rs b/crates/radicle-cli/src/git/unified_diff.rs
index 24fb8f8df3..8e1e0572a4 100644
--- a/crates/radicle-cli/src/git/unified_diff.rs
+++ b/crates/radicle-cli/src/git/unified_diff.rs
@@ -620,7 +620,7 @@ mod test {
use super::*;
#[test]
- fn test_diff_encode_decode_diff() {
+ fn diff_encode_decode_diff() {
let diff_a = diff::Diff::parse(include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/data/diff.diff"
@@ -636,7 +636,7 @@ mod test {
}
#[test]
- fn test_diff_content_encode_decode_content() {
+ fn diff_content_encode_decode_content() {
let diff_content = diff::DiffContent::parse(include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/data/diff_body.diff"
diff --git a/crates/radicle-cli/src/terminal/format.rs b/crates/radicle-cli/src/terminal/format.rs
index e3e0773962..be75fec667 100644
--- a/crates/radicle-cli/src/terminal/format.rs
+++ b/crates/radicle-cli/src/terminal/format.rs
@@ -413,10 +413,9 @@ pub mod identity {
#[cfg(test)]
mod test {
use super::*;
- use html::strip_comments;
#[test]
- fn test_strip_comments() {
+ fn strip_comments() {
let test = "\
commit 2\n\
\n\
@@ -428,7 +427,7 @@ mod test {
commit 2\n\
";
- let res = strip_comments(test);
+ let res = html::strip_comments(test);
assert_eq!(exp, res);
let test = "\
@@ -438,7 +437,7 @@ mod test {
commit 2\n\
-->";
- let res = strip_comments(test);
+ let res = html::strip_comments(test);
assert_eq!(exp, res);
let test = "\
@@ -447,7 +446,7 @@ mod test {
";
let exp = "";
- let res = strip_comments(test);
+ let res = html::strip_comments(test);
assert_eq!(exp, res);
let test = "\
@@ -464,17 +463,20 @@ mod test {
\n\
-->";
- let res = strip_comments(test);
+ let res = html::strip_comments(test);
assert_eq!(exp, res);
}
#[test]
- fn test_bytes() {
- assert_eq!(bytes(1023).to_string(), "1023 B");
- assert_eq!(bytes(1024).to_string(), "1 KiB");
- assert_eq!(bytes(1024 * 9).to_string(), "9 KiB");
- assert_eq!(bytes(1024usize.pow(2)).to_string(), "1 MiB");
- assert_eq!(bytes(1024usize.pow(2) * 56).to_string(), "56 MiB");
- assert_eq!(bytes(1024usize.pow(3) * 1024).to_string(), "1024 GiB");
+ fn bytes() {
+ assert_eq!(super::bytes(1023).to_string(), "1023 B");
+ assert_eq!(super::bytes(1024).to_string(), "1 KiB");
+ assert_eq!(super::bytes(1024 * 9).to_string(), "9 KiB");
+ assert_eq!(super::bytes(1024usize.pow(2)).to_string(), "1 MiB");
+ assert_eq!(super::bytes(1024usize.pow(2) * 56).to_string(), "56 MiB");
+ assert_eq!(
+ super::bytes(1024usize.pow(3) * 1024).to_string(),
+ "1024 GiB"
+ );
}
}
diff --git a/crates/radicle-cli/src/terminal/patch.rs b/crates/radicle-cli/src/terminal/patch.rs
index aca262abbe..9ee2c3d647 100644
--- a/crates/radicle-cli/src/terminal/patch.rs
+++ b/crates/radicle-cli/src/terminal/patch.rs
@@ -523,7 +523,7 @@ mod test {
}
#[test]
- fn test_create_display_message() {
+ fn create_display_message() {
let tmpdir = tempfile::tempdir().unwrap();
let (repo, commit_0) = fixtures::repository(&tmpdir);
let commit_1 = commit(
@@ -539,7 +539,7 @@ mod test {
"Commit 2\n\nDescription\n",
);
- let res = create_display_message(&repo, &commit_0, &commit_0).unwrap();
+ let res = super::create_display_message(&repo, &commit_0, &commit_0).unwrap();
assert_eq!(
"\
<!--\n\
@@ -555,7 +555,7 @@ mod test {
res
);
- let res = create_display_message(&repo, &commit_0, &commit_1).unwrap();
+ let res = super::create_display_message(&repo, &commit_0, &commit_1).unwrap();
assert_eq!(
"\
Commit 1\n\
@@ -575,7 +575,7 @@ mod test {
res
);
- let res = create_display_message(&repo, &commit_0, &commit_2).unwrap();
+ let res = super::create_display_message(&repo, &commit_0, &commit_2).unwrap();
assert_eq!(
"\
<!--\n\
@@ -610,8 +610,8 @@ mod test {
}
#[test]
- fn test_edit_display_message() {
- let res = edit_display_message("title", "The patch description.");
+ fn edit_display_message() {
+ let res = super::edit_display_message("title", "The patch description.");
assert_eq!(
"\
title\n\
@@ -633,7 +633,7 @@ mod test {
}
#[test]
- fn test_update_display_message() {
+ fn update_display_message() {
let tmpdir = tempfile::tempdir().unwrap();
let (repo, commit_0) = fixtures::repository(&tmpdir);
@@ -646,7 +646,7 @@ mod test {
"commit squashed",
);
- let res = update_display_message(&repo, &commit_1, &commit_1).unwrap();
+ let res = super::update_display_message(&repo, &commit_1, &commit_1).unwrap();
assert_eq!(
"\
<!--\n\
@@ -657,7 +657,7 @@ mod test {
res
);
- let res = update_display_message(&repo, &commit_1, &commit_2).unwrap();
+ let res = super::update_display_message(&repo, &commit_1, &commit_2).unwrap();
assert_eq!(
"\
commit 2\n\
@@ -670,7 +670,7 @@ mod test {
res
);
- let res = update_display_message(&repo, &commit_1, &commit_squashed).unwrap();
+ let res = super::update_display_message(&repo, &commit_1, &commit_squashed).unwrap();
assert_eq!(
"\
<!--\n\
diff --git a/crates/radicle-cli/tests/commands/clone.rs b/crates/radicle-cli/tests/commands/clone.rs
index 7e09642ef9..3787c4fa3f 100644
--- a/crates/radicle-cli/tests/commands/clone.rs
+++ b/crates/radicle-cli/tests/commands/clone.rs
@@ -276,7 +276,7 @@ fn rad_clone_unknown() {
#[test]
// User tries to clone; no seeds are available, but user has the repo locally.
-fn test_clone_without_seeds() {
+fn clone_without_seeds() {
let mut environment = Environment::new();
let mut alice = environment.node("alice");
let working = environment.tempdir().join("working");
diff --git a/crates/radicle-cli/tests/commands/cob.rs b/crates/radicle-cli/tests/commands/cob.rs
index 29654751bf..ba9cfc8919 100644
--- a/crates/radicle-cli/tests/commands/cob.rs
+++ b/crates/radicle-cli/tests/commands/cob.rs
@@ -102,7 +102,7 @@ fn rad_cob_operations() {
}
#[test]
-fn test_cob_replication() {
+fn cob_replication() {
let mut environment = Environment::new();
let working = tempfile::tempdir().unwrap();
let mut alice = environment.node("alice");
@@ -171,7 +171,7 @@ fn test_cob_replication() {
}
#[test]
-fn test_cob_deletion() {
+fn cob_deletion() {
let mut environment = Environment::new();
let working = tempfile::tempdir().unwrap();
let mut alice = environment.node("alice");
diff --git a/crates/radicle-cli/tests/commands/sync.rs b/crates/radicle-cli/tests/commands/sync.rs
index f39d292f2c..d06f2e5641 100644
--- a/crates/radicle-cli/tests/commands/sync.rs
+++ b/crates/radicle-cli/tests/commands/sync.rs
@@ -109,7 +109,7 @@ fn rad_sync() {
//
// alice -- seed -- bob
//
-fn test_replication_via_seed() {
+fn replication_via_seed() {
let mut environment = Environment::new();
let alice = environment.relay("alice");
let bob = environment.relay("bob");
diff --git a/crates/radicle-cob/src/object.rs b/crates/radicle-cob/src/object.rs
index 9b2dbaad28..a57f58f73a 100644
--- a/crates/radicle-cob/src/object.rs
+++ b/crates/radicle-cob/src/object.rs
@@ -98,7 +98,7 @@ mod tests {
use super::*;
#[test]
- fn test_serde() {
+ fn serde() {
let id = ObjectId::from_str("3ad84420bd882f983c2f9b605e7a68f5bdf95f5c").unwrap();
assert_eq!(
diff --git a/crates/radicle-crypto/src/ssh.rs b/crates/radicle-crypto/src/ssh.rs
index 8d0ff81608..38d0c36c7c 100644
--- a/crates/radicle-crypto/src/ssh.rs
+++ b/crates/radicle-crypto/src/ssh.rs
@@ -82,23 +82,23 @@ pub mod fmt {
use alloc::str::FromStr;
#[test]
- fn test_key() {
+ fn key() {
let pk =
PublicKey::from_str("z6MktWkM9vcfysWFq1c2aaLjJ6j4PYYg93TLPswR4qtuoAeT").unwrap();
assert_eq!(
- key(&pk),
+ super::key(&pk),
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINDoXIrhcnRjnLGUXUFdxhkuy08lkTOwrj2IoGsEX6+Q"
);
}
#[test]
- fn test_fingerprint() {
+ fn fingerprint() {
let pk =
PublicKey::from_str("z6MktWkM9vcfysWFq1c2aaLjJ6j4PYYg93TLPswR4qtuoAeT").unwrap();
assert_eq!(
- fingerprint(&pk),
+ super::fingerprint(&pk),
"SHA256:gE/Ty4fuXzww49lcnNe9/GI0L7xSEQdFp/v9tOjFwB4"
);
}
diff --git a/crates/radicle-crypto/src/ssh/agent.rs b/crates/radicle-crypto/src/ssh/agent.rs
index f6610cb151..03fb1023f6 100644
--- a/crates/radicle-crypto/src/ssh/agent.rs
+++ b/crates/radicle-crypto/src/ssh/agent.rs
@@ -221,7 +221,7 @@ mod test {
use crate::VerifyingKey;
#[test]
- fn test_agent_encoding_remove() {
+ fn agent_encoding_remove() {
use std::str::FromStr;
let pk =
@@ -256,7 +256,7 @@ mod test {
}
#[test]
- fn test_agent_encoding_sign() {
+ fn agent_encoding_sign() {
use std::str::FromStr;
let pk =
diff --git a/crates/radicle-crypto/src/ssh/keystore.rs b/crates/radicle-crypto/src/ssh/keystore.rs
index e43a80232e..698ad38803 100644
--- a/crates/radicle-crypto/src/ssh/keystore.rs
+++ b/crates/radicle-crypto/src/ssh/keystore.rs
@@ -240,7 +240,7 @@ mod tests {
use std::borrow::ToOwned as _;
#[test]
- fn test_init_passphrase() {
+ fn init_passphrase() {
let tmp = tempfile::tempdir().unwrap();
let store = Keystore::new(&tmp);
@@ -265,7 +265,7 @@ mod tests {
}
#[test]
- fn test_init_no_passphrase() {
+ fn init_no_passphrase() {
let tmp = tempfile::tempdir().unwrap();
let store = Keystore::new(&tmp);
@@ -279,7 +279,7 @@ mod tests {
}
#[test]
- fn test_signer() {
+ fn signer() {
let tmp = tempfile::tempdir().unwrap();
let store = Keystore::new(&tmp);
diff --git a/crates/radicle-dag/src/lib.rs b/crates/radicle-dag/src/lib.rs
index 4f59e5cc2e..7410031083 100644
--- a/crates/radicle-dag/src/lib.rs
+++ b/crates/radicle-dag/src/lib.rs
@@ -447,7 +447,7 @@ mod tests {
use super::*;
#[test]
- fn test_len() {
+ fn len() {
let mut dag = Dag::new();
dag.node(0, ());
@@ -458,7 +458,7 @@ mod tests {
}
#[test]
- fn test_is_empty() {
+ fn is_empty() {
let mut dag = Dag::new();
assert!(dag.is_empty());
@@ -467,7 +467,7 @@ mod tests {
}
#[test]
- fn test_dependencies() {
+ fn dependencies() {
let mut dag = Dag::new();
dag.node(0, ());
@@ -479,7 +479,7 @@ mod tests {
}
#[test]
- fn test_get() {
+ fn get() {
let mut dag = Dag::new();
dag.node(0, "rad");
@@ -491,7 +491,7 @@ mod tests {
}
#[test]
- fn test_cycle() {
+ fn cycle() {
let mut dag = Dag::new();
dag.node(0, ());
@@ -507,7 +507,7 @@ mod tests {
}
#[test]
- fn test_merge_1() {
+ fn merge_1() {
let mut a = Dag::new();
let mut b = Dag::new();
let mut c = Dag::new();
@@ -531,7 +531,7 @@ mod tests {
}
#[test]
- fn test_merge_2() {
+ fn merge_2() {
let mut a = Dag::new();
let mut b = Dag::new();
@@ -571,7 +571,7 @@ mod tests {
}
#[test]
- fn test_diamond() {
+ fn diamond() {
let mut dag = Dag::new();
dag.node(0, ());
@@ -595,7 +595,7 @@ mod tests {
}
#[test]
- fn test_complex() {
+ fn complex() {
let mut dag = Dag::new();
dag.node(0, ());
@@ -654,7 +654,7 @@ mod tests {
}
#[test]
- fn test_fold_sorting_1() {
+ fn fold_sorting_1() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -687,7 +687,7 @@ mod tests {
}
#[test]
- fn test_fold_sorting_2() {
+ fn fold_sorting_2() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -722,7 +722,7 @@ mod tests {
}
#[test]
- fn test_fold_diamond() {
+ fn fold_diamond() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -746,7 +746,7 @@ mod tests {
}
#[test]
- fn test_fold_multiple_roots() {
+ fn fold_multiple_roots() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -764,7 +764,7 @@ mod tests {
}
#[test]
- fn test_fold_reject() {
+ fn fold_reject() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -806,7 +806,7 @@ mod tests {
}
#[test]
- fn test_remove() {
+ fn remove() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -849,7 +849,7 @@ mod tests {
}
#[test]
- fn test_prune_1() {
+ fn prune_1() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -880,7 +880,7 @@ mod tests {
}
#[test]
- fn test_siblings() {
+ fn siblings() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -927,7 +927,7 @@ mod tests {
}
#[test]
- fn test_prune_2() {
+ fn prune_2() {
let mut dag = Dag::new();
dag.node("R", ());
@@ -962,7 +962,7 @@ mod tests {
}
#[test]
- fn test_prune_by_sorting() {
+ fn prune_by_sorting() {
let mut dag = Dag::new();
dag.node("R", 0);
@@ -1022,7 +1022,7 @@ mod tests {
}
#[test]
- fn test_contains() {
+ fn contains() {
let mut dag = Dag::<u8, ()>::new();
assert!(!dag.contains(&0));
diff --git a/crates/radicle-localtime/src/lib.rs b/crates/radicle-localtime/src/lib.rs
index 6eaa0cec29..2629a00b87 100644
--- a/crates/radicle-localtime/src/lib.rs
+++ b/crates/radicle-localtime/src/lib.rs
@@ -312,7 +312,7 @@ mod serde_impls {
use crate::LocalTime;
#[test]
- fn test_localtime() {
+ fn localtime() {
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq)]
struct Test {
time: LocalTime,
diff --git a/crates/radicle-node/src/control.rs b/crates/radicle-node/src/control.rs
index bdd7b53a09..07b29ae1a0 100644
--- a/crates/radicle-node/src/control.rs
+++ b/crates/radicle-node/src/control.rs
@@ -291,7 +291,7 @@ mod tests {
use crate::test;
#[test]
- fn test_control_socket() {
+ fn control_socket() {
let tmp = tempfile::tempdir().unwrap();
let handle = test::handle::Handle::default();
let socket = tmp.path().join("alice.sock");
@@ -341,7 +341,7 @@ mod tests {
}
#[test]
- fn test_seed_unseed() {
+ fn seed_unseed() {
let tmp = tempfile::tempdir().unwrap();
let socket = tmp.path().join("node.sock");
let proj = arbitrary::r#gen::<RepoId>(1);
diff --git a/crates/radicle-node/src/reactor/timer.rs b/crates/radicle-node/src/reactor/timer.rs
index 24b6c1c4fa..c91bfb240c 100644
--- a/crates/radicle-node/src/reactor/timer.rs
+++ b/crates/radicle-node/src/reactor/timer.rs
@@ -67,7 +67,7 @@ mod tests {
use super::*;
#[test]
- fn test_wake_exact() {
+ fn wake_exact() {
let mut tm = Timer::new();
let now = Instant::now();
@@ -80,7 +80,7 @@ mod tests {
}
#[test]
- fn test_wake() {
+ fn wake() {
let mut tm = Timer::new();
let now = Instant::now();
@@ -103,7 +103,7 @@ mod tests {
}
#[test]
- fn test_next() {
+ fn next() {
let mut tm = Timer::new();
let mut now = Instant::now();
diff --git a/crates/radicle-node/src/tests/e2e.rs b/crates/radicle-node/src/tests/e2e.rs
index cb8e1908be..affcb6c02f 100644
--- a/crates/radicle-node/src/tests/e2e.rs
+++ b/crates/radicle-node/src/tests/e2e.rs
@@ -54,7 +54,7 @@ mod config {
//
// alice -- bob
//
-fn test_inventory_sync_basic() {
+fn inventory_sync_basic() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -76,7 +76,7 @@ fn test_inventory_sync_basic() {
//
// alice -- bob -- eve
//
-fn test_inventory_sync_bridge() {
+fn inventory_sync_bridge() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -104,7 +104,7 @@ fn test_inventory_sync_bridge() {
// | |
// carol -- eve
//
-fn test_inventory_sync_ring() {
+fn inventory_sync_ring() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -139,7 +139,7 @@ fn test_inventory_sync_ring() {
// |
// carol
//
-fn test_inventory_sync_star() {
+fn inventory_sync_star() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -279,7 +279,7 @@ fn public_to_private_to_public_replay() {
}
#[test]
-fn test_replication() {
+fn replication() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -355,7 +355,7 @@ fn test_replication() {
}
#[test]
-fn test_replication_ref_in_sigrefs() {
+fn replication_ref_in_sigrefs() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -406,7 +406,7 @@ fn test_replication_ref_in_sigrefs() {
}
#[test]
-fn test_replication_invalid() {
+fn replication_invalid() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -461,7 +461,7 @@ fn test_replication_invalid() {
}
#[test]
-fn test_migrated_clone() {
+fn migrated_clone() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -518,7 +518,7 @@ fn test_migrated_clone() {
}
#[test]
-fn test_dont_fetch_owned_refs() {
+fn dont_fetch_owned_refs() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -549,7 +549,7 @@ fn test_dont_fetch_owned_refs() {
}
#[test]
-fn test_fetch_followed_remotes() {
+fn fetch_followed_remotes() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -605,7 +605,7 @@ fn test_fetch_followed_remotes() {
}
#[test]
-fn test_missing_remote() {
+fn missing_remote() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -643,7 +643,7 @@ fn test_missing_remote() {
}
#[test]
-fn test_fetch_preserve_owned_refs() {
+fn fetch_preserve_owned_refs() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -693,7 +693,7 @@ fn test_fetch_preserve_owned_refs() {
}
#[test]
-fn test_clone() {
+fn clone() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -838,7 +838,7 @@ fn clone_without_founder_namespace() {
}
#[test]
-fn test_fetch_up_to_date() {
+fn fetch_up_to_date() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -871,7 +871,7 @@ fn test_fetch_up_to_date() {
}
#[test]
-fn test_fetch_unseeded() {
+fn fetch_unseeded() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -904,7 +904,7 @@ fn test_fetch_unseeded() {
}
#[test]
-fn test_large_fetch() {
+fn large_fetch() {
let tmp = tempfile::tempdir().unwrap();
let scale = config::scale();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -938,7 +938,7 @@ fn test_large_fetch() {
}
#[test]
-fn test_concurrent_fetches() {
+fn concurrent_fetches() {
let tmp = tempfile::tempdir().unwrap();
let scale = config::scale();
let repos = scale.max(4);
@@ -1059,7 +1059,7 @@ fn test_concurrent_fetches() {
}
#[test]
-fn test_connection_crossing() {
+fn connection_crossing() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -1140,7 +1140,7 @@ fn test_connection_crossing() {
#[test]
/// Alice is going to try to fetch outdated refs of Bob, from Eve. This is a non-fast-forward fetch
/// on the sigrefs branch.
-fn test_non_fast_forward_sigrefs() {
+fn non_fast_forward_sigrefs() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1254,7 +1254,7 @@ fn test_non_fast_forward_sigrefs() {
}
#[test]
-fn test_outdated_sigrefs() {
+fn outdated_sigrefs() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1363,7 +1363,7 @@ fn test_outdated_sigrefs() {
}
#[test]
-fn test_outdated_delegate_sigrefs() {
+fn outdated_delegate_sigrefs() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1661,7 +1661,7 @@ fn missing_delegate_default_branch() {
}
#[test]
-fn test_background_foreground_fetch() {
+fn background_foreground_fetch() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1758,7 +1758,7 @@ fn test_background_foreground_fetch() {
#[test]
/// Alice is offline while Bob pushes some changes to the repo. When Alice reconnects,
/// she is made aware of the changes via the `subscribe` message, and fetches from the seed.
-fn test_catchup_on_refs_announcements() {
+fn catchup_on_refs_announcements() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -1794,7 +1794,7 @@ fn test_catchup_on_refs_announcements() {
}
#[test]
-fn test_multiple_offline_inits() {
+fn multiple_offline_inits() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1820,7 +1820,7 @@ fn test_multiple_offline_inits() {
}
#[test]
-fn test_channel_reader_limit() {
+fn channel_reader_limit() {
let tmp = tempfile::tempdir().unwrap();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
let limits = radicle::node::config::Limits {
@@ -1865,7 +1865,7 @@ fn test_channel_reader_limit() {
}
#[test]
-fn test_fetch_emits_canonical_ref_update() {
+fn fetch_emits_canonical_ref_update() {
let tmp = tempfile::tempdir().unwrap();
let scale = config::scale();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
@@ -1915,7 +1915,7 @@ fn test_fetch_emits_canonical_ref_update() {
}
#[test]
-fn test_non_fast_forward_identity_doc() {
+fn non_fast_forward_identity_doc() {
use radicle::identity::Identity;
let tmp = tempfile::tempdir().unwrap();
@@ -2033,7 +2033,7 @@ fn test_non_fast_forward_identity_doc() {
}
#[test]
-fn test_block_active_connection() {
+fn block_active_connection() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -2059,7 +2059,7 @@ fn test_block_active_connection() {
}
#[test]
-fn test_block_prevents_connection() {
+fn block_prevents_connection() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -2092,7 +2092,7 @@ fn test_block_prevents_connection() {
}
#[test]
-fn test_block_prevents_fetch() {
+fn block_prevents_fetch() {
let tmp = tempfile::tempdir().unwrap();
let alice = Node::init(tmp.path(), config::relay("alice"), 13);
let mut bob = Node::init(tmp.path(), config::relay("bob"), 37);
@@ -2165,7 +2165,7 @@ fn fetch_does_not_contain_rad_sigrefs_parent() {
}
#[test]
-fn test_fetch_emits_canonical_ref_update_partial_glob() {
+fn fetch_emits_canonical_ref_update_partial_glob() {
let tmp = tempfile::tempdir().unwrap();
let scale = config::scale();
let mut alice = Node::init(tmp.path(), config::relay("alice"), 13);
diff --git a/crates/radicle-node/src/wire.rs b/crates/radicle-node/src/wire.rs
index b099622038..9497bb1487 100644
--- a/crates/radicle-node/src/wire.rs
+++ b/crates/radicle-node/src/wire.rs
@@ -1305,7 +1305,7 @@ mod test {
use crate::wire::varint;
#[test]
- fn test_pong_message_with_extension() {
+ fn pong_message_with_extension() {
use protocol::deserializer;
let mut stream = Vec::new();
@@ -1336,7 +1336,7 @@ mod test {
}
#[test]
- fn test_inventory_ann_with_extension() {
+ fn inventory_ann_with_extension() {
use protocol::deserializer;
#[derive(Debug)]
diff --git a/crates/radicle-protocol/src/deserializer.rs b/crates/radicle-protocol/src/deserializer.rs
index 4081a6aab9..90575c7119 100644
--- a/crates/radicle-protocol/src/deserializer.rs
+++ b/crates/radicle-protocol/src/deserializer.rs
@@ -126,7 +126,7 @@ mod test {
const MSG_BYE: &[u8] = &[3, b'b', b'y', b'e'];
#[test]
- fn test_decode_next() {
+ fn decode_next() {
let mut decoder = Deserializer::<1024, String>::new(8);
decoder.input(&[3, b'b']).unwrap();
@@ -144,7 +144,7 @@ mod test {
}
#[test]
- fn test_unparsed() {
+ fn unparsed() {
let mut decoder = Deserializer::<1024, String>::new(8);
decoder.input(&[3, b'b', b'y']).unwrap();
diff --git a/crates/radicle-protocol/src/fetcher/service.rs b/crates/radicle-protocol/src/fetcher/service.rs
index 5f97112c3a..cca352507f 100644
--- a/crates/radicle-protocol/src/fetcher/service.rs
+++ b/crates/radicle-protocol/src/fetcher/service.rs
@@ -172,7 +172,7 @@ mod tests {
use crate::fetcher::{FetchConfig, MaxQueueSize};
#[test]
- fn test_fetch_coalescing_different_refs() {
+ fn fetch_coalescing_different_refs() {
let config = Config::new()
.with_max_concurrency(NonZeroUsize::new(1).unwrap())
.with_max_capacity(MaxQueueSize::new(NonZeroUsize::new(10).unwrap()));
diff --git a/crates/radicle-protocol/src/service/filter.rs b/crates/radicle-protocol/src/service/filter.rs
index ff27baf20e..2dea4fc482 100644
--- a/crates/radicle-protocol/src/service/filter.rs
+++ b/crates/radicle-protocol/src/service/filter.rs
@@ -136,7 +136,7 @@ mod test {
use radicle::test::arbitrary;
#[test]
- fn test_parameters() {
+ fn parameters() {
// To store 10'000 items with a false positive rate of 1%, we need about 12KB.
assert_eq!(bloomy::bloom::optimal_bits(10_000, 0.01) / 8, 11_981);
// To store 1'000 items with a false positive rate of 1%, we need about 1KB.
@@ -175,7 +175,7 @@ mod test {
}
#[test]
- fn test_sizes() {
+ fn sizes() {
let ids = arbitrary::vec::<RepoId>(3420);
let f = Filter::new(ids.iter().cloned().take(10));
assert_eq!(f.size(), FILTER_SIZE_S);
diff --git a/crates/radicle-protocol/src/service/gossip/store.rs b/crates/radicle-protocol/src/service/gossip/store.rs
index 27762a9264..fdc2c5ac6b 100644
--- a/crates/radicle-protocol/src/service/gossip/store.rs
+++ b/crates/radicle-protocol/src/service/gossip/store.rs
@@ -405,7 +405,7 @@ mod test {
use radicle::test::arbitrary;
#[test]
- fn test_announced() {
+ fn announced() {
let mut db = Database::memory().unwrap();
let nid = arbitrary::r#gen::<NodeId>(1);
let rid = arbitrary::r#gen::<RepoId>(1);
diff --git a/crates/radicle-protocol/src/service/limiter.rs b/crates/radicle-protocol/src/service/limiter.rs
index 5d58b6878f..2a2da85f40 100644
--- a/crates/radicle-protocol/src/service/limiter.rs
+++ b/crates/radicle-protocol/src/service/limiter.rs
@@ -155,7 +155,7 @@ mod test {
}
#[test]
- fn test_limiter_refill() {
+ fn limiter_refill() {
let mut r = RateLimiter::default();
let t = (3, 0.2); // Three tokens burst. One token every 5 seconds.
let a = HostName::Dns(String::from("seed.radicle.example.com"));
@@ -187,7 +187,7 @@ mod test {
#[test]
#[rustfmt::skip]
- fn test_limiter_multi() {
+ fn limiter_multi() {
let t = (1, 1.0); // One token per second. One token burst.
let n = arbitrary::r#gen::<NodeId>(1);
let n = Some(&n);
@@ -207,7 +207,7 @@ mod test {
#[test]
#[rustfmt::skip]
- fn test_limiter_different_rates() {
+ fn limiter_different_rates() {
let t1 = (1, 1.0); // One token per second. One token burst.
let t2 = (2, 2.0); // Two tokens per second. Two token burst.
let n = arbitrary::r#gen::<NodeId>(1);
diff --git a/crates/radicle-protocol/src/service/message.rs b/crates/radicle-protocol/src/service/message.rs
index 705b27abc0..324c6b1293 100644
--- a/crates/radicle-protocol/src/service/message.rs
+++ b/crates/radicle-protocol/src/service/message.rs
@@ -692,7 +692,7 @@ mod tests {
use super::*;
#[test]
- fn test_ref_remote_limit() {
+ fn ref_remote_limit() {
let mut refs = BoundedVec::<_, REF_REMOTE_LIMIT>::new();
let signer = SigningKey::mock(18);
let at = git::Oid::ZERO_SHA1;
@@ -724,7 +724,7 @@ mod tests {
}
#[test]
- fn test_inventory_limit() {
+ fn inventory_limit() {
let msg = Message::inventory(
InventoryAnnouncement {
inventory: arbitrary::vec(INVENTORY_LIMIT)
@@ -772,7 +772,7 @@ mod tests {
}
#[test]
- fn test_node_announcement_validate() {
+ fn node_announcement_validate() {
let ann = NodeAnnouncement {
version: 1,
features: node::Features::SEED,
diff --git a/crates/radicle-protocol/src/wire.rs b/crates/radicle-protocol/src/wire.rs
index a45e5acf01..232755f085 100644
--- a/crates/radicle-protocol/src/wire.rs
+++ b/crates/radicle-protocol/src/wire.rs
@@ -628,7 +628,7 @@ mod tests {
}
#[test]
- fn test_string() {
+ fn string() {
assert_eq!(
String::from("hello").encode_to_vec(),
vec![5, b'h', b'e', b'l', b'l', b'o']
@@ -636,7 +636,7 @@ mod tests {
}
#[test]
- fn test_alias() {
+ fn alias() {
assert_eq!(
Alias::from_str("hello").unwrap().encode_to_vec(),
vec![5, b'h', b'e', b'l', b'l', b'o']
@@ -644,7 +644,7 @@ mod tests {
}
#[test]
- fn test_filter_invalid() {
+ fn filter_invalid() {
let b = bloomy::BloomFilter::with_size(filter::FILTER_SIZE_M / 3);
let f = filter::Filter::from(b);
let bytes = f.encode_to_vec();
@@ -656,7 +656,7 @@ mod tests {
}
#[test]
- fn test_bounded_vec_limit() {
+ fn bounded_vec_limit() {
let v: BoundedVec<u8, 2> = vec![1, 2].try_into().unwrap();
let buf = &v.encode_to_vec();
diff --git a/crates/radicle-protocol/src/wire/frame.rs b/crates/radicle-protocol/src/wire/frame.rs
index 387b385ed0..50c90dd999 100644
--- a/crates/radicle-protocol/src/wire/frame.rs
+++ b/crates/radicle-protocol/src/wire/frame.rs
@@ -400,7 +400,7 @@ mod test {
use super::*;
#[test]
- fn test_stream_id() {
+ fn stream_id() {
assert_eq!(StreamId(VarInt(0b000)).kind().unwrap(), StreamType::Control);
assert_eq!(StreamId(VarInt(0b010)).kind().unwrap(), StreamType::Gossip);
assert_eq!(StreamId(VarInt(0b100)).kind().unwrap(), StreamType::Git);
@@ -419,7 +419,7 @@ mod test {
}
#[test]
- fn test_encode_git_large() {
+ fn encode_git_large() {
use wire::Encode as _;
let size = u16::MAX as usize * 3;
diff --git a/crates/radicle-protocol/src/wire/message.rs b/crates/radicle-protocol/src/wire/message.rs
index 9e615db999..945e04dab1 100644
--- a/crates/radicle-protocol/src/wire/message.rs
+++ b/crates/radicle-protocol/src/wire/message.rs
@@ -422,7 +422,7 @@ mod tests {
prop_roundtrip!(Message);
#[test]
- fn test_refs_ann_max_size() {
+ fn refs_ann_max_size() {
let signer = radicle::crypto::SigningKey::mock(235);
let refs: [RefsAt; REF_REMOTE_LIMIT] = arbitrary::r#gen(1);
let ann = AnnouncementMessage::Refs(RefsAnnouncement {
@@ -438,7 +438,7 @@ mod tests {
}
#[test]
- fn test_inv_ann_max_size() {
+ fn inv_ann_max_size() {
let signer = radicle::crypto::SigningKey::mock(147);
let inv: [RepoId; INVENTORY_LIMIT] = arbitrary::r#gen(1);
let ann = AnnouncementMessage::Inventory(InventoryAnnouncement {
@@ -453,7 +453,7 @@ mod tests {
}
#[test]
- fn test_node_ann_max_size() {
+ fn node_ann_max_size() {
let signer = radicle::crypto::SigningKey::mock(247);
let addrs: [Address; ADDRESS_LIMIT] = arbitrary::r#gen(1);
let alias = ['@'; radicle::node::MAX_ALIAS_LENGTH];
@@ -474,7 +474,7 @@ mod tests {
}
#[test]
- fn test_pingpong_encode_max_size() {
+ fn pingpong_encode_max_size() {
Message::Ping(Ping {
ponglen: 0,
zeroes: ZeroBytes::new(Ping::MAX_PING_ZEROES),
@@ -489,7 +489,7 @@ mod tests {
#[test]
#[should_panic(expected = "advance out of bounds")]
- fn test_ping_encode_size_overflow() {
+ fn ping_encode_size_overflow() {
Message::Ping(Ping {
ponglen: 0,
zeroes: ZeroBytes::new(Ping::MAX_PING_ZEROES + 1),
@@ -499,7 +499,7 @@ mod tests {
#[test]
#[should_panic(expected = "advance out of bounds")]
- fn test_pong_encode_size_overflow() {
+ fn pong_encode_size_overflow() {
Message::Pong {
zeroes: ZeroBytes::new(Ping::MAX_PONG_ZEROES + 1),
}
diff --git a/crates/radicle-protocol/src/wire/varint.rs b/crates/radicle-protocol/src/wire/varint.rs
index 325eace4fc..884f5efa48 100644
--- a/crates/radicle-protocol/src/wire/varint.rs
+++ b/crates/radicle-protocol/src/wire/varint.rs
@@ -218,12 +218,12 @@ mod test {
#[test]
#[should_panic(expected = "overflow")]
- fn test_encode_overflow() {
+ fn encode_overflow() {
VarInt(u64::MAX).encode_to_vec();
}
#[test]
- fn test_encoding() {
+ fn encoding() {
assert_eq!(VarInt(0).encode_to_vec(), vec![0x0]);
assert_eq!(VarInt(1).encode_to_vec(), vec![0x01]);
assert_eq!(VarInt(10).encode_to_vec(), vec![0x0a]);
diff --git a/crates/radicle-remote-helper/src/protocol.rs b/crates/radicle-remote-helper/src/protocol.rs
index 26d648d280..24ad04c1f4 100644
--- a/crates/radicle-remote-helper/src/protocol.rs
+++ b/crates/radicle-remote-helper/src/protocol.rs
@@ -125,7 +125,7 @@ mod tests {
use super::*;
#[test]
- fn test_capabilities() {
+ fn capabilities() {
assert_eq!(
Command::parse_line("capabilities").unwrap(),
Line::Valid(Command::Capabilities)
@@ -133,7 +133,7 @@ mod tests {
}
#[test]
- fn test_list() {
+ fn list() {
assert_eq!(
Command::parse_line("list").unwrap(),
Line::Valid(Command::List)
@@ -141,7 +141,7 @@ mod tests {
}
#[test]
- fn test_list_for_push() {
+ fn list_for_push() {
assert_eq!(
Command::parse_line("list for-push").unwrap(),
Line::Valid(Command::ListForPush)
@@ -149,7 +149,7 @@ mod tests {
}
#[test]
- fn test_fetch() {
+ fn fetch() {
assert_eq!(
Command::parse_line("fetch oid ref").unwrap(),
Line::Valid(Command::Fetch {
@@ -160,7 +160,7 @@ mod tests {
}
#[test]
- fn test_fetch_whitespace() {
+ fn fetch_whitespace() {
assert_eq!(
Command::parse_line("fetch oid ref").unwrap(),
Line::Valid(Command::Fetch {
@@ -171,7 +171,7 @@ mod tests {
}
#[test]
- fn test_push() {
+ fn push() {
assert_eq!(
Command::parse_line("push src:dst").unwrap(),
Line::Valid(Command::Push("src:dst".to_owned()))
@@ -179,7 +179,7 @@ mod tests {
}
#[test]
- fn test_push_force() {
+ fn push_force() {
assert_eq!(
Command::parse_line("push +src:dst").unwrap(),
Line::Valid(Command::Push("+src:dst".to_owned()))
@@ -187,7 +187,7 @@ mod tests {
}
#[test]
- fn test_push_delete() {
+ fn push_delete() {
assert_eq!(
Command::parse_line("push :dst").unwrap(),
Line::Valid(Command::Push(":dst".to_owned()))
@@ -195,7 +195,7 @@ mod tests {
}
#[test]
- fn test_option() {
+ fn option() {
assert_eq!(
Command::parse_line("option verbosity 2").unwrap(),
Line::Valid(Command::Option {
@@ -206,7 +206,7 @@ mod tests {
}
#[test]
- fn test_option_whitespace_preservation() {
+ fn option_whitespace_preservation() {
assert_eq!(
Command::parse_line("option patch.message Fix: whitespace").unwrap(),
Line::Valid(Command::Option {
@@ -217,13 +217,13 @@ mod tests {
}
#[test]
- fn test_empty() {
+ fn empty() {
assert_eq!(Command::parse_line("").unwrap(), Line::Blank);
assert_eq!(Command::parse_line(" ").unwrap(), Line::Blank);
}
#[test]
- fn test_invalid() {
+ fn invalid() {
assert!(Command::parse_line("invalid command").is_err());
assert!(Command::parse_line("list invalid").is_err());
}
diff --git a/crates/radicle-surf/src/test/code_browsing.rs b/crates/radicle-surf/src/test/code_browsing.rs
index 8760eb9e58..01d7237778 100644
--- a/crates/radicle-surf/src/test/code_browsing.rs
+++ b/crates/radicle-surf/src/test/code_browsing.rs
@@ -56,7 +56,7 @@ fn browse_repo_lazily() {
}
#[test]
-fn test_file_history() {
+fn file_history() {
let repo = Repository::open(platinum::get()).unwrap();
let history = repo.history(Branch::local(refname!("dev"))).unwrap();
let path = Path::new("README.md");
@@ -67,7 +67,7 @@ fn test_file_history() {
}
#[test]
-fn test_commit_history() {
+fn commit_history() {
let repo = Repository::open(platinum::get()).unwrap();
let head = "a0dd9122d33dff2a35f564d564db127152c88e02";
@@ -82,7 +82,7 @@ fn test_commit_history() {
}
#[test]
-fn test_commit_signature() {
+fn commit_signature() {
let repo = Repository::open(platinum::get()).unwrap();
let commit_with_signature = "e24124b7538658220b5aaf3b6ef53758f0a106dc";
let signature = repo.extract_signature(commit_with_signature, None).unwrap();
diff --git a/crates/radicle-surf/src/test/diff.rs b/crates/radicle-surf/src/test/diff.rs
index 263c8e3c51..710468898f 100644
--- a/crates/radicle-surf/src/test/diff.rs
+++ b/crates/radicle-surf/src/test/diff.rs
@@ -14,7 +14,7 @@ use crate::{
use super::platinum;
#[test]
-fn test_initial_diff() -> Result<(), Error> {
+fn initial_diff() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let oid = Oid::from_str("d3464e33d75c75c99bfb90fa2e9d16efc0b7d0e3")?;
let commit = repo.commit(oid).unwrap();
@@ -63,7 +63,7 @@ fn test_initial_diff() -> Result<(), Error> {
}
#[test]
-fn test_diff_of_rev() -> Result<(), Error> {
+fn diff_of_rev() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let diff = repo.diff_commit("80bacafba303bf0cdf6142921f430ff265f25095")?;
assert_eq!(diff.files().count(), 1);
@@ -71,7 +71,7 @@ fn test_diff_of_rev() -> Result<(), Error> {
}
#[test]
-fn test_diff_file() -> Result<(), Error> {
+fn diff_file() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let path_buf = Path::new("README.md").to_path_buf();
let diff = repo.diff_file(
@@ -114,7 +114,7 @@ fn test_diff_file() -> Result<(), Error> {
}
#[test]
-fn test_diff() -> Result<(), Error> {
+fn diff() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let oid = "80bacafba303bf0cdf6142921f430ff265f25095";
let commit = repo.commit(oid).unwrap();
@@ -164,7 +164,7 @@ fn test_diff() -> Result<(), Error> {
}
#[test]
-fn test_branch_diff() -> Result<(), Error> {
+fn branch_diff() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let rev_from = Branch::local(refname!("master"));
let rev_to = Branch::local(refname!("dev"));
@@ -215,7 +215,7 @@ fn test_branch_diff() -> Result<(), Error> {
#[cfg(feature = "serde")]
#[test]
-fn test_diff_serde() -> Result<(), Error> {
+fn diff_serde() -> Result<(), Error> {
let repo = Repository::open(platinum::get())?;
let rev_from = Branch::local(refname!("master"));
let rev_to = Branch::local(refname!("diff-test"));
@@ -385,7 +385,7 @@ fn test_diff_serde() -> Result<(), Error> {
#[cfg(feature = "serde")]
#[test]
-fn test_rename_with_changes() {
+fn rename_with_changes() {
let buf = r"
diff --git a/radicle/src/node/tracking/config.rs b/radicle-node/src/service/tracking.rs
similarity index 96%
@@ -595,7 +595,7 @@ index 3f69208f3..cbc843c82 100644
// https://github.com/rust-lang/rust-clippy/issues/11402
#[allow(clippy::needless_raw_string_hashes)]
#[test]
-fn test_both_missing_eof_newline() {
+fn both_missing_eof_newline() {
let buf = r#"
diff --git a/.env b/.env
index f89e4c0..7c56eb7 100644
@@ -616,7 +616,7 @@ index f89e4c0..7c56eb7 100644
}
#[test]
-fn test_none_missing_eof_newline() {
+fn none_missing_eof_newline() {
let buf = r#"
diff --git a/.env b/.env
index f89e4c0..7c56eb7 100644
@@ -635,7 +635,7 @@ index f89e4c0..7c56eb7 100644
}
#[test]
-fn test_old_missing_eof_newline() {
+fn old_missing_eof_newline() {
let buf = r#"
diff --git a/.env b/.env
index f89e4c0..7c56eb7 100644
@@ -655,7 +655,7 @@ index f89e4c0..7c56eb7 100644
}
#[test]
-fn test_new_missing_eof_newline() {
+fn new_missing_eof_newline() {
let buf = r#"
diff --git a/.env b/.env
index f89e4c0..7c56eb7 100644
diff --git a/crates/radicle-surf/src/test/reference.rs b/crates/radicle-surf/src/test/reference.rs
index cb3490bede..8f16aa401c 100644
--- a/crates/radicle-surf/src/test/reference.rs
+++ b/crates/radicle-surf/src/test/reference.rs
@@ -4,7 +4,7 @@ use radicle_git_ref_format::pattern;
use super::platinum;
#[test]
-fn test_branches() {
+fn branches() {
let repo = Repository::open(platinum::get()).unwrap();
let heads = Glob::all_heads();
let branches = repo.branches(heads.clone()).unwrap();
@@ -20,7 +20,7 @@ fn test_branches() {
}
#[test]
-fn test_tag_snapshot() {
+fn tag_snapshot() {
let repo = Repository::open(platinum::get()).unwrap();
let tags = repo
.tags(&Glob::all_tags())
@@ -33,7 +33,7 @@ fn test_tag_snapshot() {
}
#[test]
-fn test_namespaces() {
+fn namespaces() {
let repo = Repository::open(platinum::get()).unwrap();
let namespaces = repo.namespaces(&Glob::all_namespaces()).unwrap();
diff --git a/crates/radicle-surf/src/test/source.rs b/crates/radicle-surf/src/test/source.rs
index 7666ee9b94..92fabb0b8d 100644
--- a/crates/radicle-surf/src/test/source.rs
+++ b/crates/radicle-surf/src/test/source.rs
@@ -56,7 +56,7 @@ fn tree_serialization() {
}
#[test]
-fn test_tree_last_commit() {
+fn tree_last_commit() {
let repo = Repository::open(platinum::get()).unwrap();
let tree = repo.tree(refname!("refs/heads/master"), &"src").unwrap();
let last_commit = tree.last_commit(&repo).unwrap();
diff --git a/crates/radicle-surf/src/test/submodule.rs b/crates/radicle-surf/src/test/submodule.rs
index a2dd637a76..ae2536a569 100644
--- a/crates/radicle-surf/src/test/submodule.rs
+++ b/crates/radicle-surf/src/test/submodule.rs
@@ -11,7 +11,7 @@ use super::r#gen;
proptest! {
#[test]
- fn test_submodule(
+ fn submodule(
initial in r#gen::commit::commit(),
commits in collection::vec(r#gen::commit::commit(), 1..5)
) {
@@ -20,7 +20,7 @@ proptest! {
#[ignore = "segfault"]
#[test]
- fn test_submodule_bare(
+ fn submodule_bare(
initial in r#gen::commit::commit(),
commits in collection::vec(r#gen::commit::commit(), 1..5)
) {
diff --git a/crates/radicle-term/src/cell.rs b/crates/radicle-term/src/cell.rs
index 48c3785aa9..cd6931548c 100644
--- a/crates/radicle-term/src/cell.rs
+++ b/crates/radicle-term/src/cell.rs
@@ -210,7 +210,7 @@ impl<T: Cell + fmt::Display> Cell for Filled<T> {
#[cfg(test)]
mod test {
#[test]
- fn test_width() {
+ fn width() {
assert_eq!(unicode_display_width::width("❤️"), 2);
assert_eq!(unicode_display_width::width("🪵"), 2);
}
diff --git a/crates/radicle-term/src/element.rs b/crates/radicle-term/src/element.rs
index b9d29105b0..245b2d9760 100644
--- a/crates/radicle-term/src/element.rs
+++ b/crates/radicle-term/src/element.rs
@@ -378,7 +378,7 @@ mod test {
use super::*;
#[test]
- fn test_truncate() {
+ fn truncate() {
let line = Line::default().item("banana").item("peach").item("apple");
let mut actual = line.clone();
@@ -399,7 +399,7 @@ mod test {
}
#[test]
- fn test_width() {
+ fn width() {
// Nb. This might not display correctly in some editors or terminals.
let line = Line::new("Radicle Heartwood Protocol & Stack ❤️🪵");
assert_eq!(line.width(), 39, "{line}");
@@ -410,7 +410,7 @@ mod test {
}
#[test]
- fn test_spaced() {
+ fn spaced() {
let line = Line::spaced(["banana", "peach", "apple"].into_iter().map(Label::new));
let iterated: Vec<_> = line.into_iter().collect();
diff --git a/crates/radicle-term/src/table.rs b/crates/radicle-term/src/table.rs
index 6e4e1aefd2..83d01b48a3 100644
--- a/crates/radicle-term/src/table.rs
+++ b/crates/radicle-term/src/table.rs
@@ -259,7 +259,7 @@ mod test {
use pretty_assertions::assert_eq;
#[test]
- fn test_truncate() {
+ fn truncate() {
assert_eq!("🍍".truncate(1, "…"), String::from("…"));
assert_eq!("🍍".truncate(1, ""), String::from(""));
assert_eq!("🍍🍍".truncate(2, "…"), String::from("…"));
@@ -272,7 +272,7 @@ mod test {
}
#[test]
- fn test_table() {
+ fn table() {
let mut t = Table::new(TableOptions::default());
t.push(["pineapple", "rosemary"]);
@@ -289,7 +289,7 @@ mod test {
}
#[test]
- fn test_table_border() {
+ fn table_border() {
let mut t = Table::new(TableOptions {
border: Some(Color::Unset),
spacing: 3,
@@ -326,7 +326,7 @@ mod test {
}
#[test]
- fn test_table_border_truncated() {
+ fn table_border_truncated() {
let mut t = Table::new(TableOptions {
border: Some(Color::Unset),
spacing: 3,
@@ -367,7 +367,7 @@ mod test {
}
#[test]
- fn test_table_border_maximized() {
+ fn table_border_maximized() {
let mut t = Table::new(TableOptions {
border: Some(Color::Unset),
spacing: 3,
@@ -411,7 +411,7 @@ mod test {
}
#[test]
- fn test_table_truncate() {
+ fn table_truncate() {
let mut t = Table::default();
let constrain = Constraint::new(
Size::MIN,
@@ -435,7 +435,7 @@ mod test {
}
#[test]
- fn test_table_unicode() {
+ fn table_unicode() {
let mut t = Table::new(TableOptions::default());
t.push(["🍍pineapple", "__rosemary", "__sage"]);
@@ -452,7 +452,7 @@ mod test {
}
#[test]
- fn test_table_unicode_truncate() {
+ fn table_unicode_truncate() {
let mut t = Table::new(TableOptions {
..TableOptions::default()
});
diff --git a/crates/radicle-term/src/textarea.rs b/crates/radicle-term/src/textarea.rs
index af6c00058e..c4b43e0996 100644
--- a/crates/radicle-term/src/textarea.rs
+++ b/crates/radicle-term/src/textarea.rs
@@ -98,7 +98,7 @@ mod test {
use pretty_assertions::assert_eq;
#[test]
- fn test_wrapping() {
+ fn wrapping() {
let t = TextArea::new(
"Radicle enables users to run their own nodes, \
ensuring censorship-resistant code collaboration \
@@ -120,7 +120,7 @@ mod test {
}
#[test]
- fn test_wrapping_paragraphs() {
+ fn wrapping_paragraphs() {
let t = TextArea::new(
"Radicle enables users to run their own nodes, \
ensuring censorship-resistant code collaboration \
@@ -151,7 +151,7 @@ mod test {
}
#[test]
- fn test_wrapping_code_block() {
+ fn wrapping_code_block() {
let t = TextArea::new(
"\
Here's an example:
@@ -179,7 +179,7 @@ Run the above and wait for your project to sync.\
}
#[test]
- fn test_wrapping_fenced_block() {
+ fn wrapping_fenced_block() {
let t = TextArea::new(
"\
Here's an example:
diff --git a/crates/radicle-term/src/vstack.rs b/crates/radicle-term/src/vstack.rs
index 65372f16a6..4f327f33f7 100644
--- a/crates/radicle-term/src/vstack.rs
+++ b/crates/radicle-term/src/vstack.rs
@@ -215,7 +215,7 @@ mod test {
use pretty_assertions::assert_eq;
#[test]
- fn test_vstack() {
+ fn vstack() {
let mut v = VStack::default().border(Some(Color::Unset)).padding(1);
v.push(Line::new("banana"));
@@ -245,7 +245,7 @@ mod test {
}
#[test]
- fn test_vstack_maximize() {
+ fn vstack_maximize() {
let mut v = VStack::default().border(Some(Color::Unset)).padding(1);
v.push(Line::new("banana"));
diff --git a/crates/radicle/src/cob/cache.rs b/crates/radicle/src/cob/cache.rs
index cbcb3c3e22..6140dbf7ac 100644
--- a/crates/radicle/src/cob/cache.rs
+++ b/crates/radicle/src/cob/cache.rs
@@ -449,7 +449,7 @@ mod tests {
use crate::assert_matches;
#[test]
- fn test_check_version() {
+ fn check_version() {
let mut db = StoreWriter::memory().unwrap();
assert_matches!(db.check_version(), Err(Error::OutOfDate));
@@ -458,7 +458,7 @@ mod tests {
}
#[test]
- fn test_migrate_to() {
+ fn migrate_to() {
let mut db = StoreWriter::memory().unwrap();
assert_eq!(db.version().unwrap(), 0);
diff --git a/crates/radicle/src/cob/cache/migrations/2.rs b/crates/radicle/src/cob/cache/migrations/2.rs
index e67a6fc84c..5a41952bce 100644
--- a/crates/radicle/src/cob/cache/migrations/2.rs
+++ b/crates/radicle/src/cob/cache/migrations/2.rs
@@ -86,7 +86,7 @@ mod tests {
const PATCH_V2: &str = include_str!("samples/patch.v2.json");
#[test]
- fn test_migration_2() {
+ fn migration_2() {
let mut db = StoreWriter::memory().unwrap();
db.migrate_to(1, migrate::ignore).unwrap();
db.raw_query(|conn| {
@@ -125,7 +125,7 @@ mod tests {
}
#[test]
- fn test_patch_json_deserialization() {
+ fn patch_json_deserialization() {
serde_json::from_str::<crate::cob::patch::Patch>(PATCH_V1).unwrap_err();
serde_json::from_str::<crate::cob::patch::Patch>(PATCH_V2).unwrap();
}
diff --git a/crates/radicle/src/cob/common.rs b/crates/radicle/src/cob/common.rs
index db9bee1bd7..bfd5126609 100644
--- a/crates/radicle/src/cob/common.rs
+++ b/crates/radicle/src/cob/common.rs
@@ -525,7 +525,7 @@ mod test {
use super::*;
#[test]
- fn test_title() {
+ fn title() {
assert_eq!(Title::new(""), Err(TitleError::EmptyTitle));
assert_eq!(Title::new(" "), Err(TitleError::EmptyTitle));
assert_eq!(Title::new("\t"), Err(TitleError::EmptyTitle));
@@ -535,7 +535,7 @@ mod test {
}
#[test]
- fn test_color() {
+ fn color() {
let c = Color::from_str("#ffccaa").unwrap();
assert_eq!(c.to_string(), "#ffccaa".to_owned());
assert_eq!(serde_json::to_string(&c).unwrap(), "\"#ffccaa\"".to_owned());
@@ -555,7 +555,7 @@ mod test {
}
#[test]
- fn test_emojis() {
+ fn emojis() {
let emojis = emojis::Group::SmileysAndEmotion
.emojis()
.chain(emojis::Group::PeopleAndBody.emojis())
diff --git a/crates/radicle/src/cob/identity.rs b/crates/radicle/src/cob/identity.rs
index c90ca0323b..9afe0b7ab3 100644
--- a/crates/radicle/src/cob/identity.rs
+++ b/crates/radicle/src/cob/identity.rs
@@ -1398,7 +1398,7 @@ mod test {
}
#[test]
- fn test_identity_updates() {
+ fn identity_updates() {
let NodeWithRepo { node, repo } = NodeWithRepo::default();
let bob = SigningKey::mock(103);
let signer = &node.signer;
@@ -1461,7 +1461,7 @@ mod test {
}
#[test]
- fn test_identity_update_rejected() {
+ fn identity_update_rejected() {
let NodeWithRepo { node, repo } = NodeWithRepo::default();
let bob = SigningKey::mock(200);
let eve = SigningKey::mock(201);
@@ -1541,7 +1541,7 @@ mod test {
}
#[test]
- fn test_identity_updates_concurrent() {
+ fn identity_updates_concurrent() {
let network = Network::default();
let alice = &network.alice;
let bob = &network.bob;
@@ -1613,7 +1613,7 @@ mod test {
}
#[test]
- fn test_identity_redact_revision() {
+ fn identity_redact_revision() {
let network = Network::default();
let alice = &network.alice;
let bob = &network.bob;
@@ -1972,7 +1972,7 @@ mod test {
}
#[test]
- fn test_identity_updates_concurrent_outdated() {
+ fn identity_updates_concurrent_outdated() {
let network = Network::default();
let alice = &network.alice;
let bob = &network.bob;
@@ -2253,7 +2253,7 @@ mod test {
}
#[test]
- fn test_identity_cannot_redact_terminal_states() {
+ fn identity_cannot_redact_terminal_states() {
let network = Network::default();
let alice = &network.alice;
let bob = &network.bob;
@@ -2571,7 +2571,7 @@ mod test {
}
#[test]
- fn test_valid_identity() {
+ fn valid_identity() {
let tempdir = tempfile::tempdir().unwrap();
let mut rng = fastrand::Rng::new();
diff --git a/crates/radicle/src/cob/issue.rs b/crates/radicle/src/cob/issue.rs
index c31f349a14..b5c829cc00 100644
--- a/crates/radicle/src/cob/issue.rs
+++ b/crates/radicle/src/cob/issue.rs
@@ -945,7 +945,7 @@ mod test {
use crate::{assert_matches, test};
#[test]
- fn test_concurrency() {
+ fn concurrency() {
let t = test::setup::Network::default();
let mut alice_issues = Cache::no_cache(&*t.alice.repo, &t.alice.signer).unwrap();
@@ -1016,7 +1016,7 @@ mod test {
}
#[test]
- fn test_ordering() {
+ fn ordering() {
assert!(CloseReason::Solved > CloseReason::Other);
assert!(
State::Open
@@ -1027,7 +1027,7 @@ mod test {
}
#[test]
- fn test_issue_create_and_assign() {
+ fn issue_create_and_assign() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1063,7 +1063,7 @@ mod test {
}
#[test]
- fn test_issue_create_and_reassign() {
+ fn issue_create_and_reassign() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1095,7 +1095,7 @@ mod test {
}
#[test]
- fn test_issue_create_and_get() {
+ fn issue_create_and_get() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let created = issues
@@ -1120,7 +1120,7 @@ mod test {
}
#[test]
- fn test_issue_create_and_change_state() {
+ fn issue_create_and_change_state() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1156,7 +1156,7 @@ mod test {
}
#[test]
- fn test_issue_create_and_unassign() {
+ fn issue_create_and_unassign() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1183,7 +1183,7 @@ mod test {
}
#[test]
- fn test_issue_edit() {
+ fn issue_edit() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1207,7 +1207,7 @@ mod test {
}
#[test]
- fn test_issue_edit_description() {
+ fn issue_edit_description() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1232,7 +1232,7 @@ mod test {
}
#[test]
- fn test_issue_react() {
+ fn issue_react() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1261,7 +1261,7 @@ mod test {
}
#[test]
- fn test_issue_reply() {
+ fn issue_reply() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1307,7 +1307,7 @@ mod test {
}
#[test]
- fn test_issue_label() {
+ fn issue_label() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let bug_label = Label::new("bug").unwrap();
@@ -1338,7 +1338,7 @@ mod test {
}
#[test]
- fn test_issue_comment() {
+ fn issue_comment() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let author = node.signer.public_key();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1374,7 +1374,7 @@ mod test {
}
#[test]
- fn test_issue_comment_redact() {
+ fn issue_comment_redact() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1403,7 +1403,7 @@ mod test {
}
#[test]
- fn test_issue_state_serde() {
+ fn issue_state_serde() {
assert_eq!(
serde_json::to_value(State::Open).unwrap(),
serde_json::json!({ "status": "open" })
@@ -1419,7 +1419,7 @@ mod test {
}
#[test]
- fn test_issue_all() {
+ fn issue_all() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
issues
@@ -1447,7 +1447,7 @@ mod test {
}
#[test]
- fn test_issue_multilines() {
+ fn issue_multilines() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let created = issues
@@ -1472,7 +1472,7 @@ mod test {
}
#[test]
- fn test_embeds() {
+ fn embeds() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1525,7 +1525,7 @@ mod test {
}
#[test]
- fn test_embeds_edit() {
+ fn embeds_edit() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
@@ -1573,7 +1573,7 @@ mod test {
}
#[test]
- fn test_invalid_actions() {
+ fn invalid_actions() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1604,7 +1604,7 @@ mod test {
}
#[test]
- fn test_invalid_tx() {
+ fn invalid_tx() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let mut issue = issues
@@ -1630,7 +1630,7 @@ mod test {
}
#[test]
- fn test_invalid_tx_reference() {
+ fn invalid_tx_reference() {
let test::setup::NodeWithRepo { node, repo, .. } = test::setup::NodeWithRepo::default();
let mut issues = Cache::no_cache(&*repo, &node.signer).unwrap();
let issue = issues
@@ -1652,7 +1652,7 @@ mod test {
}
#[test]
- fn test_invalid_cob() {
+ fn invalid_cob() {
use cob::change::Storage as _;
use cob::object::Storage as _;
use nonempty::NonEmpty;
diff --git a/crates/radicle/src/cob/issue/cache.rs b/crates/radicle/src/cob/issue/cache.rs
index d4af802ab8..fffdbb23d9 100644
--- a/crates/radicle/src/cob/issue/cache.rs
+++ b/crates/radicle/src/cob/issue/cache.rs
@@ -642,7 +642,7 @@ mod tests {
}
#[test]
- fn test_is_empty() {
+ fn is_empty() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
assert!(cache.is_empty().unwrap());
@@ -664,7 +664,7 @@ mod tests {
}
#[test]
- fn test_counts() {
+ fn counts() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let n_open = arbitrary::r#gen::<u8>(0);
@@ -705,7 +705,7 @@ mod tests {
}
#[test]
- fn test_get() {
+ fn get() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -740,7 +740,7 @@ mod tests {
}
#[test]
- fn test_list() {
+ fn list() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -770,7 +770,7 @@ mod tests {
}
#[test]
- fn test_list_by_status() {
+ fn list_by_status() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -800,7 +800,7 @@ mod tests {
}
#[test]
- fn test_remove() {
+ fn remove() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
diff --git a/crates/radicle/src/cob/patch.rs b/crates/radicle/src/cob/patch.rs
index bdfd6e8391..7b83ca4cf3 100644
--- a/crates/radicle/src/cob/patch.rs
+++ b/crates/radicle/src/cob/patch.rs
@@ -3068,7 +3068,7 @@ mod test {
}
#[test]
- fn test_target_branch() {
+ fn target_branch() {
let unqualified = TargetBranch::try_from("master").unwrap();
assert_eq!(unqualified.as_str(), "refs/heads/master");
@@ -3092,7 +3092,7 @@ mod test {
}
#[test]
- fn test_json_serialisation_target() {
+ fn json_serialisation_target() {
let edit_none = Action::Edit {
title: cob::Title::new("My patch").unwrap(),
target: MergeTarget::Delegates,
@@ -3115,7 +3115,7 @@ mod test {
}
#[test]
- fn test_merge_target_resolution() {
+ fn merge_target_resolution() {
let alice = SigningKey::mock(23);
let project = Project::new(
ProjectName::from_str("test_merge_target_resolution").unwrap(),
@@ -3170,7 +3170,7 @@ mod test {
}
#[test]
- fn test_patch_merge_authorization_ref_formats() {
+ fn patch_merge_authorization_ref_formats() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
@@ -3253,7 +3253,7 @@ mod test {
}
#[test]
- fn test_patch_merge_custom_destination_authorized() {
+ fn patch_merge_custom_destination_authorized() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
@@ -3312,7 +3312,7 @@ mod test {
}
#[test]
- fn test_patch_merge_custom_destination_unauthorized() {
+ fn patch_merge_custom_destination_unauthorized() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let alice = SigningKey::mock(14);
@@ -3371,7 +3371,7 @@ mod test {
}
#[test]
- fn test_json_serialization() {
+ fn json_serialization() {
let edit = Action::Label {
labels: BTreeSet::new(),
};
@@ -3382,7 +3382,7 @@ mod test {
}
#[test]
- fn test_reactions_json_serialization() {
+ fn reactions_json_serialization() {
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
struct TestReactions {
@@ -3424,7 +3424,7 @@ mod test {
}
#[test]
- fn test_patch_create_and_get() {
+ fn patch_create_and_get() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3465,7 +3465,7 @@ mod test {
}
#[test]
- fn test_patch_discussion() {
+ fn patch_discussion() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3497,7 +3497,7 @@ mod test {
}
#[test]
- fn test_patch_merge() {
+ fn patch_merge() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3527,7 +3527,7 @@ mod test {
}
#[test]
- fn test_patch_review() {
+ fn patch_review() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3577,7 +3577,7 @@ mod test {
}
#[test]
- fn test_patch_review_revision_redact() {
+ fn patch_review_revision_redact() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3607,7 +3607,7 @@ mod test {
}
#[test]
- fn test_revision_review_merge_redacted() {
+ fn revision_review_merge_redacted() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let mut alice = SigningKey::mock(14);
@@ -3665,7 +3665,7 @@ mod test {
}
#[test]
- fn test_revision_edit_redact() {
+ fn revision_edit_redact() {
let base = arbitrary::oid();
let oid = arbitrary::oid();
let repo = r#gen::<MockRepository>(1);
@@ -3726,7 +3726,7 @@ mod test {
}
#[test]
- fn test_revision_reaction() {
+ fn revision_reaction() {
let base = git::Oid::from_str("cb18e95ada2bb38aadd8e6cef0963ce37a87add3").unwrap();
let oid = git::Oid::from_str("518d5069f94c03427f694bb494ac1cd7d1339380").unwrap();
let mut alice = SigningKey::mock(35);
@@ -3764,7 +3764,7 @@ mod test {
}
#[test]
- fn test_patch_review_edit() {
+ fn patch_review_edit() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3801,7 +3801,7 @@ mod test {
}
#[test]
- fn test_patch_review_duplicate() {
+ fn patch_review_duplicate() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3831,7 +3831,7 @@ mod test {
}
#[test]
- fn test_patch_review_edit_comment() {
+ fn patch_review_edit_comment() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3880,7 +3880,7 @@ mod test {
}
#[test]
- fn test_patch_review_comment() {
+ fn patch_review_comment() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3925,7 +3925,7 @@ mod test {
}
#[test]
- fn test_patch_review_remove_summary() {
+ fn patch_review_remove_summary() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -3965,7 +3965,7 @@ mod test {
}
#[test]
- fn test_patch_update() {
+ fn patch_update() {
let alice = test::setup::NodeWithRepo::default();
let checkout = alice.repo.checkout();
let branch = checkout.branch_with([("README", b"Hello World!")]);
@@ -4019,7 +4019,7 @@ mod test {
}
#[test]
- fn test_patch_redact() {
+ fn patch_redact() {
let alice = test::setup::Node::default();
let repo = alice.project();
let branch = repo
@@ -4056,7 +4056,7 @@ mod test {
}
#[test]
- fn test_json() {
+ fn json() {
use serde_json::json;
assert_eq!(
diff --git a/crates/radicle/src/cob/patch/actions.rs b/crates/radicle/src/cob/patch/actions.rs
index 17a2405f35..3c04a5a591 100644
--- a/crates/radicle/src/cob/patch/actions.rs
+++ b/crates/radicle/src/cob/patch/actions.rs
@@ -188,7 +188,7 @@ mod test {
use super::ReviewEdit;
#[test]
- fn test_review_edit() {
+ fn review_edit() {
let v1 = json!({
"type": "review.edit",
"review": "89d45fb371eb2622ba88188d474347cc526d80bb",
diff --git a/crates/radicle/src/cob/patch/cache.rs b/crates/radicle/src/cob/patch/cache.rs
index 3b05415674..7e78385752 100644
--- a/crates/radicle/src/cob/patch/cache.rs
+++ b/crates/radicle/src/cob/patch/cache.rs
@@ -766,7 +766,7 @@ mod tests {
}
#[test]
- fn test_is_empty() {
+ fn is_empty() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
assert!(cache.is_empty().unwrap());
@@ -794,7 +794,7 @@ mod tests {
}
#[test]
- fn test_counts() {
+ fn counts() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let n_open = arbitrary::r#gen::<u8>(0);
@@ -882,7 +882,7 @@ mod tests {
}
#[test]
- fn test_get() {
+ fn get() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -918,7 +918,7 @@ mod tests {
}
#[test]
- fn test_find_by_revision() {
+ fn find_by_revision() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let patch_id = PatchId::from(arbitrary::oid());
@@ -960,7 +960,7 @@ mod tests {
}
#[test]
- fn test_list() {
+ fn list() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -991,7 +991,7 @@ mod tests {
}
#[test]
- fn test_list_by_status() {
+ fn list_by_status() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
@@ -1022,7 +1022,7 @@ mod tests {
}
#[test]
- fn test_remove() {
+ fn remove() {
let repo = arbitrary::r#gen::<MockRepository>(1);
let mut cache = memory(&repo);
let ids = (0..arbitrary::r#gen::<u8>(1))
diff --git a/crates/radicle/src/cob/patch/encoding/review.rs b/crates/radicle/src/cob/patch/encoding/review.rs
index ae626effad..45b46ca1ad 100644
--- a/crates/radicle/src/cob/patch/encoding/review.rs
+++ b/crates/radicle/src/cob/patch/encoding/review.rs
@@ -134,7 +134,7 @@ mod test {
use super::{Review, Summary};
#[test]
- fn test_review_summary() {
+ fn review_summary() {
let summary_null = json!(null);
let summary_string = json!("lgtm");
let summary_edits = json!([{
@@ -165,7 +165,7 @@ mod test {
}
#[test]
- fn test_review_deserialize_summary_migration_null_summary() {
+ fn review_deserialize_summary_migration_null_summary() {
let review = json!({
"id": "89d45fb371eb2622ba88188d474347cc526d80bb",
"author": { "id": "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx" },
@@ -186,7 +186,7 @@ mod test {
}
#[test]
- fn test_review_deserialize_summary_migration_without_summary() {
+ fn review_deserialize_summary_migration_without_summary() {
let review = json!({
"id": "89d45fb371eb2622ba88188d474347cc526d80bb",
"author": { "id": "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx" },
@@ -206,7 +206,7 @@ mod test {
}
#[test]
- fn test_review_deserialize_summary_migration_with_summary() {
+ fn review_deserialize_summary_migration_with_summary() {
let review = json!({
"id": "89d45fb371eb2622ba88188d474347cc526d80bb",
"author": { "id": "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx" },
@@ -227,7 +227,7 @@ mod test {
}
#[test]
- fn test_review_deserialize_summary_v2() {
+ fn review_deserialize_summary_v2() {
let review = json!({
"id": "89d45fb371eb2622ba88188d474347cc526d80bb",
"author": { "id": "did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx" },
diff --git a/crates/radicle/src/cob/stream.rs b/crates/radicle/src/cob/stream.rs
index 6a37f06cd7..0512c28d88 100644
--- a/crates/radicle/src/cob/stream.rs
+++ b/crates/radicle/src/cob/stream.rs
@@ -329,7 +329,7 @@ mod tests {
}
#[test]
- fn test_all_from() {
+ fn all_from() {
let tmp = tempfile::tempdir().unwrap();
let (repo, _) = test::fixtures::repository(tmp.path());
let signer = SigningKey::mock(38);
@@ -343,7 +343,7 @@ mod tests {
}
#[test]
- fn test_all_until() {
+ fn all_until() {
let tmp = tempfile::tempdir().unwrap();
let (repo, _) = test::fixtures::repository(tmp.path());
let signer = SigningKey::mock(39);
@@ -358,7 +358,7 @@ mod tests {
}
#[test]
- fn test_all_from_until() {
+ fn all_from_until() {
let tmp = tempfile::tempdir().unwrap();
let (repo, _) = test::fixtures::repository(tmp.path());
let signer = SigningKey::mock(40);
@@ -373,7 +373,7 @@ mod tests {
}
#[test]
- fn test_from_until() {
+ fn from_until() {
let tmp = tempfile::tempdir().unwrap();
let (repo, _) = test::fixtures::repository(tmp.path());
let signer = SigningKey::mock(41);
@@ -396,7 +396,7 @@ mod tests {
}
#[test]
- fn test_regression_from_until() {
+ fn regression_from_until() {
let tmp = tempfile::tempdir().unwrap();
let (repo, _) = test::fixtures::repository(tmp.path());
let signer = SigningKey::mock(42);
diff --git a/crates/radicle/src/cob/thread.rs b/crates/radicle/src/cob/thread.rs
index 451376e707..db8ccd2db9 100644
--- a/crates/radicle/src/cob/thread.rs
+++ b/crates/radicle/src/cob/thread.rs
@@ -664,7 +664,7 @@ mod tests {
impl<T> SignerThreadOpExt for T where T: SignerOpExt {}
#[test]
- fn test_redact_comment() {
+ fn redact_comment() {
let radicle::test::setup::Node { signer, .. } = radicle::test::setup::Node::default();
let repo = r#gen::<MockRepository>(1);
let mut alice = signer;
@@ -689,7 +689,7 @@ mod tests {
}
#[test]
- fn test_edit_comment() {
+ fn edit_comment() {
let mut alice = SigningKey::mock(49);
let repo = r#gen::<MockRepository>(1);
@@ -761,7 +761,7 @@ mod tests {
}
#[test]
- fn test_timeline() {
+ fn timeline() {
let alice = SigningKey::mock(94);
let bob = SigningKey::mock(103);
let eve = SigningKey::mock(104);
@@ -829,7 +829,7 @@ mod tests {
}
#[test]
- fn test_duplicate_comments() {
+ fn duplicate_comments() {
let repo = r#gen::<MockRepository>(1);
let alice = SigningKey::mock(94);
let bob = SigningKey::mock(103);
@@ -934,7 +934,7 @@ mod tests {
}
#[test]
- fn test_comment_redact_missing() {
+ fn comment_redact_missing() {
let repo = r#gen::<MockRepository>(1);
let mut alice = SigningKey::mock(94);
let mut t = Thread::default();
@@ -944,7 +944,7 @@ mod tests {
}
#[test]
- fn test_comment_edit_missing() {
+ fn comment_edit_missing() {
let repo = r#gen::<MockRepository>(1);
let mut alice = SigningKey::mock(94);
let mut t = Thread::default();
@@ -954,7 +954,7 @@ mod tests {
}
#[test]
- fn test_comment_edit_redacted() {
+ fn comment_edit_redacted() {
let repo = r#gen::<MockRepository>(1);
let mut alice = SigningKey::mock(94);
diff --git a/crates/radicle/src/git/canonical.rs b/crates/radicle/src/git/canonical.rs
index 128daace54..8d4c57d50a 100644
--- a/crates/radicle/src/git/canonical.rs
+++ b/crates/radicle/src/git/canonical.rs
@@ -556,7 +556,7 @@ mod tests {
}
#[test]
- fn test_quorum_properties() {
+ fn quorum_properties() {
let tmp = tempfile::tempdir().unwrap();
let (repo, c0) = fixtures::repository(tmp.path());
let c0: crate::git::Oid = c0.into();
@@ -590,7 +590,7 @@ mod tests {
}
#[test]
- fn test_quorum_different_types() {
+ fn quorum_different_types() {
let tmp = tempfile::tempdir().unwrap();
let (repo, c0) = fixtures::repository(tmp.path());
let t0 = fixtures::tag("v1", "", c0, &repo);
@@ -602,7 +602,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_groups() {
+ fn commit_quorum_groups() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -635,7 +635,7 @@ mod tests {
}
#[test]
- fn test_tag_quorum() {
+ fn tag_quorum() {
let t1 = tag("0480391dd7312d35c79a455ec5d004657260b358");
let t2 = tag("a2eec713ec5c287ecdf13a0180f68acfef7962d0");
@@ -654,7 +654,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_single() {
+ fn commit_quorum_single() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -673,7 +673,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_linear() {
+ fn commit_quorum_linear() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -729,7 +729,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_two_way_fork() {
+ fn commit_quorum_two_way_fork() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -837,7 +837,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_three_way_fork() {
+ fn commit_quorum_three_way_fork() {
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
let c3 = commit("07c2a0f856e0d6b08115f98a265df88c4e507fa0");
@@ -917,7 +917,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_fork_of_a_fork() {
+ fn commit_quorum_fork_of_a_fork() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -1200,7 +1200,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_forked_merge_commits() {
+ fn commit_quorum_forked_merge_commits() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
@@ -1466,7 +1466,7 @@ mod tests {
}
#[test]
- fn test_commit_quorum_merges() {
+ fn commit_quorum_merges() {
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
let m1 = commit("dd7ee5bca2fc7288a6efcb4303278e26a2dbaa45");
let m2 = commit("d54e505e3fb5c0c7e4b9a4b8a1cdeefb3fc9ef18");
diff --git a/crates/radicle/src/git/canonical/quorum.rs b/crates/radicle/src/git/canonical/quorum.rs
index 6e805f76d3..d915b90286 100644
--- a/crates/radicle/src/git/canonical/quorum.rs
+++ b/crates/radicle/src/git/canonical/quorum.rs
@@ -269,7 +269,7 @@ mod test {
}
#[test]
- fn test_merge_bases() {
+ fn merge_bases() {
let c0 = commit("f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354");
let c1 = commit("bfb1a513e420eade90b0e6be64117b861b16ecb5");
let c2 = commit("8fc5160702365f231c77732a8fa162379e54f57a");
diff --git a/crates/radicle/src/identity/did.rs b/crates/radicle/src/identity/did.rs
index fb61c98888..a956256286 100644
--- a/crates/radicle/src/identity/did.rs
+++ b/crates/radicle/src/identity/did.rs
@@ -108,7 +108,7 @@ mod test {
use super::*;
#[test]
- fn test_did_encode_decode() {
+ fn did_encode_decode() {
let input = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";
let Did(key) = Did::decode(input).unwrap();
@@ -116,7 +116,7 @@ mod test {
}
#[test]
- fn test_did_vectors() {
+ fn did_vectors() {
Did::decode("did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp").unwrap();
Did::decode("did:key:z6MkjchhfUsD6mmvni8mCdXHw216Xrm9bQe2mBH1P5RDjVJG").unwrap();
Did::decode("did:key:z6MknGc3ocHs3zdPiJbnaaqDi58NGb4pk1Sp9WxWufuXSdxf").unwrap();
diff --git a/crates/radicle/src/identity/doc.rs b/crates/radicle/src/identity/doc.rs
index 25a554cdd0..756a7a36e5 100644
--- a/crates/radicle/src/identity/doc.rs
+++ b/crates/radicle/src/identity/doc.rs
@@ -1133,7 +1133,7 @@ mod test {
use qcheck_macros::quickcheck;
#[test]
- fn test_duplicate_dids() {
+ fn duplicate_dids() {
let delegate = SigningKey::mock(usize::MAX);
let did = Did::from(delegate.public_key());
let mut doc = RawDoc::new(r#gen::<Project>(1), vec![did], 1, Visibility::Public);
@@ -1144,7 +1144,7 @@ mod test {
}
#[test]
- fn test_max_delegates() {
+ fn max_delegates() {
// Generate more than the max delegates
let delegates = arbitrary::set::<Did>(MAX_DELEGATES + 1..=MAX_DELEGATES + 1)
.into_iter()
@@ -1165,7 +1165,7 @@ mod test {
}
#[test]
- fn test_is_valid_version() {
+ fn is_valid_version() {
// 0 is not a valid version
assert!(!Version::is_valid_version(&0));
@@ -1180,7 +1180,7 @@ mod test {
}
#[test]
- fn test_future_version_error() {
+ fn future_version_error() {
let v = Version(NonZeroU32::MAX).to_string();
assert_eq!(
serde_json::from_str::<Version>(&v)
@@ -1191,7 +1191,7 @@ mod test {
}
#[test]
- fn test_parse_version() {
+ fn parse_version() {
// Original document before introducing the version field
let v1 = json!(
{
@@ -1265,7 +1265,7 @@ mod test {
}
#[test]
- fn test_canonical_example() {
+ fn canonical_example() {
let tempdir = tempfile::tempdir().unwrap();
let storage = Storage::open(tempdir.path().join("storage"), fixtures::user()).unwrap();
@@ -1296,7 +1296,7 @@ mod test {
}
#[test]
- fn test_not_found() {
+ fn not_found() {
let tempdir = tempfile::tempdir().unwrap();
let storage = Storage::open(tempdir.path().join("storage"), fixtures::user()).unwrap();
let remote = arbitrary::r#gen::<RemoteId>(1);
@@ -1315,7 +1315,7 @@ mod test {
}
#[test]
- fn test_canonical_doc() {
+ fn canonical_doc() {
let tempdir = tempfile::tempdir().unwrap();
let storage = Storage::open(tempdir.path().join("storage"), fixtures::user()).unwrap();
transport::local::register(storage.clone());
@@ -1345,7 +1345,7 @@ mod test {
}
#[test]
- fn test_visibility_json() {
+ fn visibility_json() {
use std::str::FromStr;
assert_eq!(
diff --git a/crates/radicle/src/identity/doc/update.rs b/crates/radicle/src/identity/doc/update.rs
index 26d090cf28..cc3ee8a9b6 100644
--- a/crates/radicle/src/identity/doc/update.rs
+++ b/crates/radicle/src/identity/doc/update.rs
@@ -305,7 +305,7 @@ mod test {
use super::PayloadUpsert;
#[test]
- fn test_can_update_crefs() {
+ fn can_update_crefs() {
let raw = arbitrary::r#gen::<RawDoc>(1);
let raw = super::payload(
raw,
@@ -326,7 +326,7 @@ mod test {
}
#[test]
- fn test_cannot_include_default_branch_rule() {
+ fn cannot_include_default_branch_rule() {
let raw = arbitrary::r#gen::<RawDoc>(1);
let project = raw.project().unwrap().unwrap();
let branch = project.default_branch_qualified();
@@ -358,7 +358,7 @@ mod test {
}
#[test]
- fn test_default_branch_rule_exists_after_verification() {
+ fn default_branch_rule_exists_after_verification() {
let raw = arbitrary::r#gen::<RawDoc>(1);
let project = raw.project().unwrap().unwrap();
let branch = project.default_branch_qualified();
diff --git a/crates/radicle/src/identity/project.rs b/crates/radicle/src/identity/project.rs
index d652440be6..308d8a4d77 100644
--- a/crates/radicle/src/identity/project.rs
+++ b/crates/radicle/src/identity/project.rs
@@ -283,7 +283,7 @@ mod test {
use crate::assert_matches;
#[test]
- fn test_project_name() {
+ fn project_name() {
assert_matches!(serde_json::from_str::<ProjectName>("\"\""), Err(_));
assert_matches!(
serde_json::from_str::<ProjectName>("\"invalid name\""),
diff --git a/crates/radicle/src/node.rs b/crates/radicle/src/node.rs
index 01eba76bc4..6e873bcd73 100644
--- a/crates/radicle/src/node.rs
+++ b/crates/radicle/src/node.rs
@@ -1592,7 +1592,7 @@ mod test {
use crate::assert_matches;
#[test]
- fn test_user_agent() {
+ fn user_agent() {
assert!(UserAgent::from_str("/radicle:1.0.0/").is_ok());
assert!(UserAgent::from_str("/radicle:1.0.0/heartwood:0.9/").is_ok());
assert!(UserAgent::from_str("/radicle:1.0.0/heartwood:0.9/rust:1.77/").is_ok());
@@ -1614,7 +1614,7 @@ mod test {
}
#[test]
- fn test_alias() {
+ fn alias() {
assert!(Alias::from_str("cloudhead").is_ok());
assert!(Alias::from_str("cloud-head").is_ok());
assert!(Alias::from_str("cl0ud.h3ad$__").is_ok());
@@ -1629,7 +1629,7 @@ mod test {
}
#[test]
- fn test_address() {
+ fn address() {
assert!(Address::from_str("127.0.0.1:8776").is_ok());
assert!(Address::from_str("[::1]:8776").is_ok());
assert!(Address::from_str("[::ffff:127.0.0.1]:8776").is_ok());
@@ -1645,7 +1645,7 @@ mod test {
}
#[test]
- fn test_command_result() {
+ fn command_result() {
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Test {
value: u32,
diff --git a/crates/radicle/src/node/address/store.rs b/crates/radicle/src/node/address/store.rs
index 54e3ed34ae..117ea3a842 100644
--- a/crates/radicle/src/node/address/store.rs
+++ b/crates/radicle/src/node/address/store.rs
@@ -622,7 +622,7 @@ mod test {
use localtime::LocalTime;
#[test]
- fn test_empty() {
+ fn empty() {
let tmp = tempfile::tempdir().unwrap();
let path = tmp.path().join("cache");
let cache = Database::open(path, crate::node::db::config::Config::default()).unwrap();
@@ -631,7 +631,7 @@ mod test {
}
#[test]
- fn test_get_none() {
+ fn get_none() {
let alice = arbitrary::r#gen::<NodeId>(1);
let cache = Database::memory().unwrap();
let result = cache.get(&alice).unwrap();
@@ -640,7 +640,7 @@ mod test {
}
#[test]
- fn test_remove_nothing() {
+ fn remove_nothing() {
let alice = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
let removed = cache.remove(&alice).unwrap();
@@ -649,7 +649,7 @@ mod test {
}
#[test]
- fn test_alias() {
+ fn alias() {
let alice = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
let features = node::Features::SEED;
@@ -688,7 +688,7 @@ mod test {
}
#[test]
- fn test_insert_and_get() {
+ fn insert_and_get() {
let alice = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
let version = 2;
@@ -728,7 +728,7 @@ mod test {
}
#[test]
- fn test_insert_duplicate() {
+ fn insert_duplicate() {
let alice = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
let features = node::Features::SEED;
@@ -757,7 +757,7 @@ mod test {
}
#[test]
- fn test_insert_and_update() {
+ fn insert_and_update() {
let alice = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
let timestamp = LocalTime::now().into();
@@ -832,7 +832,7 @@ mod test {
}
#[test]
- fn test_insert_and_remove() {
+ fn insert_and_remove() {
let alice = arbitrary::r#gen::<NodeId>(1);
let bob = arbitrary::r#gen::<NodeId>(1);
let mut cache = Database::memory().unwrap();
@@ -882,7 +882,7 @@ mod test {
}
#[test]
- fn test_entries() {
+ fn entries() {
let ids = arbitrary::vec::<NodeId>(16);
let mut rng = fastrand::Rng::new();
let mut cache = Database::memory().unwrap();
@@ -924,7 +924,7 @@ mod test {
}
#[test]
- fn test_disconnected() {
+ fn disconnected() {
let alice = arbitrary::r#gen::<NodeId>(1);
let addr = arbitrary::r#gen::<Address>(1);
let mut cache = Database::memory().unwrap();
@@ -965,7 +965,7 @@ mod test {
}
#[test]
- fn test_disconnected_ban() {
+ fn disconnected_ban() {
let alice = arbitrary::r#gen::<NodeId>(1);
let ua = UserAgent::default();
let ip1: net::Ipv4Addr = [198, 18, 0, 8].into();
@@ -1029,7 +1029,7 @@ mod test {
}
#[test]
- fn test_entries_skips_unparsable_address() {
+ fn entries_skips_unparsable_address() {
let alice = arbitrary::r#gen::<NodeId>(1);
let bob = arbitrary::r#gen::<NodeId>(2);
let mut cache = Database::memory().unwrap();
@@ -1077,7 +1077,7 @@ mod test {
}
#[test]
- fn test_node_aliases() {
+ fn node_aliases() {
let mut db = Database::memory().unwrap();
let input = node::properties::AliasInput::new();
let (short, short_ids) = input.short();
diff --git a/crates/radicle/src/node/db.rs b/crates/radicle/src/node/db.rs
index 68d4654387..d717ec6fd7 100644
--- a/crates/radicle/src/node/db.rs
+++ b/crates/radicle/src/node/db.rs
@@ -245,7 +245,7 @@ mod test {
use super::*;
#[test]
- fn test_version() {
+ fn version() {
let n = MIGRATIONS.len();
let db = Database::memory().unwrap();
assert_eq!(db.version().unwrap(), n);
diff --git a/crates/radicle/src/node/features.rs b/crates/radicle/src/node/features.rs
index a643b2072d..26c7744d08 100644
--- a/crates/radicle/src/node/features.rs
+++ b/crates/radicle/src/node/features.rs
@@ -113,7 +113,7 @@ mod test {
use super::*;
#[test]
- fn test_operations() {
+ fn operations() {
assert_eq!(Features::NONE.with(Features::SEED), Features::SEED);
assert!(
diff --git a/crates/radicle/src/node/notifications/store.rs b/crates/radicle/src/node/notifications/store.rs
index cda113428f..018d0bf740 100644
--- a/crates/radicle/src/node/notifications/store.rs
+++ b/crates/radicle/src/node/notifications/store.rs
@@ -421,7 +421,7 @@ mod test {
use super::*;
#[test]
- fn test_clear() {
+ fn clear() {
let mut db = Store::open(":memory:").unwrap();
let repo = arbitrary::r#gen::<RepoId>(1);
let old = arbitrary::oid();
@@ -444,7 +444,7 @@ mod test {
}
#[test]
- fn test_counts_by_repo() {
+ fn counts_by_repo() {
let mut db = Store::open(":memory:").unwrap();
let repo1 = arbitrary::r#gen::<RepoId>(1);
let repo2 = arbitrary::r#gen::<RepoId>(1);
@@ -478,7 +478,7 @@ mod test {
}
#[test]
- fn test_branch_notifications() {
+ fn branch_notifications() {
let repo = arbitrary::r#gen::<RepoId>(1);
let old = arbitrary::oid();
let master = arbitrary::oid();
@@ -556,7 +556,7 @@ mod test {
}
#[test]
- fn test_notification_status() {
+ fn notification_status() {
let repo = arbitrary::r#gen::<RepoId>(1);
let oid = arbitrary::oid();
let time = LocalTime::from_millis(32188142);
@@ -599,7 +599,7 @@ mod test {
}
#[test]
- fn test_duplicate_notifications() {
+ fn duplicate_notifications() {
let repo = arbitrary::r#gen::<RepoId>(1);
let old = arbitrary::oid();
let master1 = arbitrary::oid();
@@ -647,7 +647,7 @@ mod test {
}
#[test]
- fn test_cob_notifications() {
+ fn cob_notifications() {
let repo = arbitrary::r#gen::<RepoId>(1);
let old = arbitrary::oid();
let new = arbitrary::oid();
diff --git a/crates/radicle/src/node/policy/store.rs b/crates/radicle/src/node/policy/store.rs
index c7c1c18478..e0b3c8db08 100644
--- a/crates/radicle/src/node/policy/store.rs
+++ b/crates/radicle/src/node/policy/store.rs
@@ -465,7 +465,7 @@ mod test {
use crate::test::arbitrary;
#[test]
- fn test_follow_and_unfollow_node() {
+ fn follow_and_unfollow_node() {
let id = arbitrary::r#gen::<NodeId>(1);
let mut db = Store::open(":memory:").unwrap();
let eve = Alias::new("eve");
@@ -478,7 +478,7 @@ mod test {
}
#[test]
- fn test_seed_and_unseed_repo() {
+ fn seed_and_unseed_repo() {
let id = arbitrary::r#gen::<RepoId>(1);
let mut db = Store::open(":memory:").unwrap();
@@ -490,7 +490,7 @@ mod test {
}
#[test]
- fn test_node_policies() {
+ fn node_policies() {
let ids = arbitrary::vec::<NodeId>(3);
let mut db = Store::open(":memory:").unwrap();
@@ -504,7 +504,7 @@ mod test {
}
#[test]
- fn test_repo_policies() {
+ fn repo_policies() {
let ids = arbitrary::vec::<RepoId>(3);
let mut db = Store::open(":memory:").unwrap();
@@ -518,7 +518,7 @@ mod test {
}
#[test]
- fn test_update_alias() {
+ fn update_alias() {
let id = arbitrary::r#gen::<NodeId>(1);
let mut db = Store::open(":memory:").unwrap();
@@ -538,7 +538,7 @@ mod test {
}
#[test]
- fn test_update_scope() {
+ fn update_scope() {
let id = arbitrary::r#gen::<RepoId>(1);
let mut db = Store::open(":memory:").unwrap();
@@ -555,7 +555,7 @@ mod test {
}
#[test]
- fn test_repo_policy() {
+ fn repo_policy() {
let id = arbitrary::r#gen::<RepoId>(1);
let mut db = Store::open(":memory:").unwrap();
@@ -567,7 +567,7 @@ mod test {
}
#[test]
- fn test_node_policy() {
+ fn node_policy() {
let id = arbitrary::r#gen::<NodeId>(1);
let mut db = Store::open(":memory:").unwrap();
@@ -584,7 +584,7 @@ mod test {
}
#[test]
- fn test_node_aliases() {
+ fn node_aliases() {
let mut db = Store::open(":memory:").unwrap();
let input = node::properties::AliasInput::new();
let (short, short_ids) = input.short();
diff --git a/crates/radicle/src/node/refs/store.rs b/crates/radicle/src/node/refs/store.rs
index 614a7c5b2e..0c030b659f 100644
--- a/crates/radicle/src/node/refs/store.rs
+++ b/crates/radicle/src/node/refs/store.rs
@@ -181,7 +181,7 @@ mod test {
use localtime::{LocalDuration, LocalTime};
#[test]
- fn test_count() {
+ fn count() {
let mut db = Database::memory().unwrap();
let oid = arbitrary::oid();
@@ -209,7 +209,7 @@ mod test {
}
#[test]
- fn test_set_and_delete() {
+ fn set_and_delete() {
let mut db = Database::memory().unwrap();
let oid = arbitrary::oid();
@@ -226,7 +226,7 @@ mod test {
}
#[test]
- fn test_set_and_get() {
+ fn set_and_get() {
let mut db = Database::memory().unwrap();
let oid1 = arbitrary::oid();
let oid2 = arbitrary::oid();
diff --git a/crates/radicle/src/node/routing.rs b/crates/radicle/src/node/routing.rs
index 25bfce5a85..f39db28c3f 100644
--- a/crates/radicle/src/node/routing.rs
+++ b/crates/radicle/src/node/routing.rs
@@ -273,7 +273,7 @@ mod test {
}
#[test]
- fn test_insert_and_get() {
+ fn insert_and_get() {
let ids = arbitrary::set::<RepoId>(5..10);
let nodes = arbitrary::set::<NodeId>(5..10);
let mut db = database(":memory:");
@@ -296,7 +296,7 @@ mod test {
}
#[test]
- fn test_insert_and_get_resources() {
+ fn insert_and_get_resources() {
let ids = arbitrary::set::<RepoId>(5..10);
let nodes = arbitrary::set::<NodeId>(5..10);
let mut db = database(":memory:");
@@ -314,7 +314,7 @@ mod test {
}
#[test]
- fn test_entries() {
+ fn entries() {
let ids = arbitrary::set::<RepoId>(6..9);
let nodes = arbitrary::set::<NodeId>(6..9);
let mut db = database(":memory:");
@@ -338,7 +338,7 @@ mod test {
}
#[test]
- fn test_insert_and_remove() {
+ fn insert_and_remove() {
let ids = arbitrary::set::<RepoId>(5..10);
let nodes = arbitrary::set::<NodeId>(5..10);
let mut db = database(":memory:");
@@ -357,7 +357,7 @@ mod test {
}
#[test]
- fn test_insert_duplicate() {
+ fn insert_duplicate() {
let id = arbitrary::r#gen::<RepoId>(1);
let node = arbitrary::r#gen::<NodeId>(1);
let mut db = database(":memory:");
@@ -377,7 +377,7 @@ mod test {
}
#[test]
- fn test_insert_existing_updated_time() {
+ fn insert_existing_updated_time() {
let id = arbitrary::r#gen::<RepoId>(1);
let node = arbitrary::r#gen::<NodeId>(1);
let mut db = database(":memory:");
@@ -398,7 +398,7 @@ mod test {
}
#[test]
- fn test_update_existing_multi() {
+ fn update_existing_multi() {
let id1 = arbitrary::r#gen::<RepoId>(1);
let id2 = arbitrary::r#gen::<RepoId>(1);
let node = arbitrary::r#gen::<NodeId>(1);
@@ -427,7 +427,7 @@ mod test {
}
#[test]
- fn test_remove_redundant() {
+ fn remove_redundant() {
let id = arbitrary::r#gen::<RepoId>(1);
let node = arbitrary::r#gen::<NodeId>(1);
let mut db = database(":memory:");
@@ -441,7 +441,7 @@ mod test {
}
#[test]
- fn test_remove_many() {
+ fn remove_many() {
let id1 = arbitrary::r#gen::<RepoId>(1);
let id2 = arbitrary::r#gen::<RepoId>(1);
let id3 = arbitrary::r#gen::<RepoId>(1);
@@ -457,7 +457,7 @@ mod test {
}
#[test]
- fn test_len() {
+ fn len() {
let mut db = database(":memory:");
let ids = arbitrary::vec::<RepoId>(10);
let node = arbitrary::r#gen(1);
@@ -469,7 +469,7 @@ mod test {
}
#[test]
- fn test_prune() {
+ fn prune() {
let mut rng = fastrand::Rng::new();
let now = LocalTime::now();
let ids = arbitrary::vec::<RepoId>(10);
@@ -503,7 +503,7 @@ mod test {
}
#[test]
- fn test_count() {
+ fn count() {
let id = arbitrary::r#gen::<RepoId>(1);
let nodes = arbitrary::set::<NodeId>(5..10);
let mut db = database(":memory:");
diff --git a/crates/radicle/src/node/timestamp.rs b/crates/radicle/src/node/timestamp.rs
index 9af6380c23..6b60d4c23d 100644
--- a/crates/radicle/src/node/timestamp.rs
+++ b/crates/radicle/src/node/timestamp.rs
@@ -125,7 +125,7 @@ mod tests {
use super::*;
#[test]
- fn test_timestamp_max() {
+ fn timestamp_max() {
assert_eq!(i64::try_from(*Timestamp::MAX), Ok(i64::MAX));
}
}
diff --git a/crates/radicle/src/profile.rs b/crates/radicle/src/profile.rs
index 513900844f..e74ed9066a 100644
--- a/crates/radicle/src/profile.rs
+++ b/crates/radicle/src/profile.rs
@@ -900,7 +900,7 @@ mod test {
}
#[test]
- fn test_config() {
+ fn config() {
let cfg = json::from_value::<Config>(json::json!({
"publicExplorer": "https://app.radicle.example.com/nodes/$host/$rid$path",
"preferredSeeds": [],
diff --git a/crates/radicle/src/rad.rs b/crates/radicle/src/rad.rs
index 85d7951f50..b8644af311 100644
--- a/crates/radicle/src/rad.rs
+++ b/crates/radicle/src/rad.rs
@@ -517,7 +517,7 @@ mod tests {
use super::*;
#[test]
- fn test_init() {
+ fn init() {
let tempdir = tempfile::tempdir().unwrap();
let signer = SigningKey::mock(73);
let public_key = signer.public_key();
@@ -526,7 +526,7 @@ mod tests {
transport::local::register(storage.clone());
let (repo, _) = fixtures::repository(tempdir.path().join("working"));
- let (proj, _, refs) = init(
+ let (proj, _, refs) = super::init(
&repo,
"acme".try_into().unwrap(),
"Acme's repo",
@@ -569,7 +569,7 @@ mod tests {
}
#[test]
- fn test_fork() {
+ fn fork() {
let mut rng = fastrand::Rng::new();
let tempdir = tempfile::tempdir().unwrap();
let alice = SigningKey::mock(rng.usize(..));
@@ -581,7 +581,7 @@ mod tests {
// Alice creates a project.
let (original, _) = fixtures::repository(tempdir.path().join("original"));
- let (id, _, alice_refs) = init(
+ let (id, _, alice_refs) = super::init(
&original,
"acme".try_into().unwrap(),
"Acme's repo",
@@ -593,8 +593,8 @@ mod tests {
.unwrap();
// Bob forks it and creates a checkout.
- fork(id, &bob, &storage).unwrap();
- checkout(id, bob_id, tempdir.path().join("copy"), &storage, false).unwrap();
+ super::fork(id, &bob, &storage).unwrap();
+ super::checkout(id, bob_id, tempdir.path().join("copy"), &storage, false).unwrap();
let bob_remote = storage.repository(id).unwrap().remote(bob_id).unwrap();
@@ -608,7 +608,7 @@ mod tests {
}
#[test]
- fn test_checkout() {
+ fn checkout() {
let tempdir = tempfile::tempdir().unwrap();
let signer = SigningKey::mock(73);
let remote_id = signer.public_key();
@@ -617,7 +617,7 @@ mod tests {
transport::local::register(storage.clone());
let (original, _) = fixtures::repository(tempdir.path().join("original"));
- let (id, _, _) = init(
+ let (id, _, _) = super::init(
&original,
"acme".try_into().unwrap(),
"Acme's repo",
@@ -629,7 +629,8 @@ mod tests {
.unwrap();
git::set_upstream(&original, "rad", "master", "refs/heads/master").unwrap();
- let copy = checkout(id, remote_id, tempdir.path().join("copy"), &storage, false).unwrap();
+ let copy =
+ super::checkout(id, remote_id, tempdir.path().join("copy"), &storage, false).unwrap();
assert_eq!(
copy.head().unwrap().target(),
diff --git a/crates/radicle/src/storage.rs b/crates/radicle/src/storage.rs
index aee6b110d4..09c8ac3def 100644
--- a/crates/radicle/src/storage.rs
+++ b/crates/radicle/src/storage.rs
@@ -793,5 +793,5 @@ where
#[cfg(test)]
mod tests {
#[test]
- fn test_storage() {}
+ fn storage() {}
}
diff --git a/crates/radicle/src/storage/git.rs b/crates/radicle/src/storage/git.rs
index 51503bc8ed..267f98568c 100644
--- a/crates/radicle/src/storage/git.rs
+++ b/crates/radicle/src/storage/git.rs
@@ -1161,7 +1161,7 @@ mod tests {
use crate::test::fixtures;
#[test]
- fn test_references_of() {
+ fn references_of() {
let tmp = tempfile::tempdir().unwrap();
let signer = SigningKey::mock(54);
let storage = Storage::open(tmp.path().join("storage"), fixtures::user()).unwrap();
@@ -1195,7 +1195,7 @@ mod tests {
}
#[test]
- fn test_sign_refs() {
+ fn sign_refs() {
let tmp = tempfile::tempdir().unwrap();
let signer = SigningKey::mock(0xb4);
let storage = Storage::open(tmp.path(), fixtures::user()).unwrap();
diff --git a/crates/radicle/src/storage/git/transport/local/url.rs b/crates/radicle/src/storage/git/transport/local/url.rs
index ba07c14863..14e068bbbb 100644
--- a/crates/radicle/src/storage/git/transport/local/url.rs
+++ b/crates/radicle/src/storage/git/transport/local/url.rs
@@ -106,7 +106,7 @@ mod test {
use super::*;
#[test]
- fn test_url_parse() {
+ fn url_parse() {
let repo = RepoId::from_canonical("z2w8RArM3gaBXZxXhQUswE3hhLcss").unwrap();
let namespace =
Namespace::from_str("z6Mkifeb5NPS6j7JP72kEQEeuqMTpCAVcHsJi1C86jGTzHRi").unwrap();
@@ -142,7 +142,7 @@ mod test {
}
#[test]
- fn test_url_to_string() {
+ fn url_to_string() {
let repo = RepoId::from_canonical("z2w8RArM3gaBXZxXhQUswE3hhLcss").unwrap();
let namespace =
Namespace::from_str("z6Mkifeb5NPS6j7JP72kEQEeuqMTpCAVcHsJi1C86jGTzHRi").unwrap();
diff --git a/crates/radicle/src/storage/git/transport/remote/url.rs b/crates/radicle/src/storage/git/transport/remote/url.rs
index fd548349f1..08be247141 100644
--- a/crates/radicle/src/storage/git/transport/remote/url.rs
+++ b/crates/radicle/src/storage/git/transport/remote/url.rs
@@ -108,7 +108,7 @@ mod test {
use super::*;
#[test]
- fn test_url_parse() {
+ fn url_parse() {
let node = NodeId::from_str("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK").unwrap();
let repo = RepoId::from_canonical("z2w8RArM3gaBXZxXhQUswE3hhLcss").unwrap();
let namespace =
diff --git a/crates/radicle/src/storage/refs.rs b/crates/radicle/src/storage/refs.rs
index d9c25895a3..51b00402a9 100644
--- a/crates/radicle/src/storage/refs.rs
+++ b/crates/radicle/src/storage/refs.rs
@@ -519,7 +519,7 @@ mod tests {
// to `london`. We expect that this does not cause the canonical head of the `london` repo
// to change, despite Bob being a delegate of both repos, because the refs were signed for the
// `paris` repo. We also don't expected the signed refs to validate without error.
- fn test_rid_verification() {
+ fn rid_verification() {
let tmp = tempfile::tempdir().unwrap();
let alice = SigningKey::mock(9);
let bob = SigningKey::mock(10);
diff --git a/crates/radicle/src/test/assert.rs b/crates/radicle/src/test/assert.rs
index 13942dd655..7111a61500 100644
--- a/crates/radicle/src/test/assert.rs
+++ b/crates/radicle/src/test/assert.rs
@@ -135,7 +135,7 @@ mod test {
}
#[test]
- fn test_assert_succeed() {
+ fn assert_succeed() {
let a = Foo::A(123);
assert_matches!(a, Foo::A(_));
@@ -166,7 +166,7 @@ mod test {
#[test]
#[should_panic]
- fn test_assert_panic_0() {
+ fn assert_panic_0() {
let a = Foo::A(123);
assert_matches!(a, Foo::B(_));
@@ -174,7 +174,7 @@ mod test {
#[test]
#[should_panic]
- fn test_assert_panic_1() {
+ fn assert_panic_1() {
let b = Foo::B("foo");
assert_matches!(b, Foo::B("bar"));
@@ -182,14 +182,14 @@ mod test {
#[test]
#[should_panic]
- fn test_assert_panic_2() {
+ fn assert_panic_2() {
let b = Foo::B("foo");
assert_matches!(b, Foo::B(s) if s == "bar");
}
#[test]
- fn test_assert_no_move() {
+ fn assert_no_move() {
let b = &mut Foo::A(0);
assert_matches!(*b, Foo::A(0));
}
@@ -226,7 +226,7 @@ mod test {
}
#[test]
- fn test_panic_message() {
+ fn panic_message_format() {
let a = Foo::A(1);
// expr, pat
diff --git a/crates/radicle/src/version.rs b/crates/radicle/src/version.rs
index b390e10bbb..4b2b04453b 100644
--- a/crates/radicle/src/version.rs
+++ b/crates/radicle/src/version.rs
@@ -38,7 +38,7 @@ mod test {
use super::*;
#[test]
- fn test_version() {
+ fn version() {
let mut buffer = Vec::new();
Version {
name: "rad",
commit 7e1cb406bb935c3de008d2171e8961f57b4336ea
Author: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
Date: Tue Sep 8 11:26:03 2026 +0200
build/Dockerfile: Bump `cargo-zigbuild`
This is required for compatiblity with Rust.
diff --git a/build/Dockerfile b/build/Dockerfile
index ab619d98be..f1d4e87a10 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -40,7 +40,7 @@ RUN rustup target add \
# We use Zig as the linker to perform the compilation from a Linux host.
# Zig is not yet available on Debian, so we download the official binary.
# Compilation is done via `cargo-zigbuild` which is a wrapper around `zig`.
-RUN cargo install --locked cargo-zigbuild@0.22.1
+RUN cargo install --locked cargo-zigbuild@0.23.4
# Parts of the macOS SDK are required to build Radicle, we make these available
# here. So far only `CoreFoundation` and `Security` frameworks are needed.
Exit code: 0
shell: 'export RUSTDOCFLAGS=''-D warnings'' cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny warnings cargo build --all-targets --workspace cargo doc --workspace --no-deps --all-features cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name 96c9545b-f698-4e88-986a-49d537f839ae -v /opt/radcis/ci.rad.levitte.org/cci/state/96c9545b-f698-4e88-986a-49d537f839ae/s:/96c9545b-f698-4e88-986a-49d537f839ae/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/96c9545b-f698-4e88-986a-49d537f839ae/w:/96c9545b-f698-4e88-986a-49d537f839ae/w -w /96c9545b-f698-4e88-986a-49d537f839ae/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /96c9545b-f698-4e88-986a-49d537f839ae/s/script.sh
+ export 'RUSTDOCFLAGS=-D warnings'
+ RUSTDOCFLAGS='-D warnings'
+ cargo --version
info: syncing channel updates for '1.98.0-x86_64-unknown-linux-gnu'
info: latest update on 2026-08-20, rust version 1.98.0 (88d9e12ae 2026-08-18)
info: downloading component 'cargo'
info: downloading component 'clippy'
info: downloading component 'rust-docs'
info: downloading component 'rust-src'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: downloading component 'rustfmt'
info: installing component 'cargo'
info: installing component 'clippy'
info: installing component 'rust-docs'
info: installing component 'rust-src'
info: installing component 'rust-std'
info: installing component 'rustc'
info: installing component 'rustfmt'
cargo 1.98.0 (797e8a9bc 2026-08-05)
+ rustc --version
rustc 1.98.0 (88d9e12ae 2026-08-18)
+ cargo fmt --check
+ cargo clippy --all-targets --workspace -- --deny warnings
Updating crates.io index
Downloading crates ...
Downloaded cipher v0.4.4
Downloaded addr2line v0.25.1
Downloaded clap_builder v4.6.0
Downloaded clap_complete v4.6.0
Downloaded clap v4.6.0
Downloaded data-encoding-macro v0.1.19
Downloaded data-encoding-macro-internal v0.1.17
Downloaded chrono v0.4.44
Downloaded clap_derive v4.6.0
Downloaded clap_lex v1.1.0
Downloaded cypheraddr v0.4.1
Downloaded data-encoding v2.10.0
Downloaded qcheck-macros v1.0.0
Downloaded rand_chacha v0.3.1
Downloaded quote v1.0.45
Downloaded cyphernet v0.5.4
Downloaded cyphergraphy v0.3.1
Downloaded gix-sec v0.14.0
Downloaded rand v0.8.5
Downloaded quick-error v1.2.3
Downloaded rand v0.9.2
Downloaded gix-object v0.60.0
Downloaded ed25519 v2.2.3
Downloaded cpufeatures v0.2.17
Downloaded crypto-bigint v0.5.5
Downloaded gix-negotiate v0.31.0
Downloaded ssh-encoding v0.2.0
Downloaded const-oid v0.9.6
Downloaded fluent-uri v0.3.2
Downloaded gix-commitgraph v0.37.0
Downloaded spki v0.7.3
Downloaded gix-command v0.9.0
Downloaded crossbeam-channel v0.5.15
Downloaded gix-path v0.12.0
Downloaded signal-hook-mio v0.2.5
Downloaded schemars v1.2.1
Downloaded der v0.7.10
Downloaded derive_more-impl v2.1.1
Downloaded rsa v0.9.10
Downloaded digest v0.10.7
Downloaded equivalent v1.0.2
Downloaded ff v0.13.1
Downloaded crypto-common v0.1.7
Downloaded fast-glob v0.3.3
Downloaded faster-hex v0.10.0
Downloaded serde_spanned v1.0.4
Downloaded sval_json v2.17.0
Downloaded rand_chacha v0.9.0
Downloaded siphasher v1.0.2
Downloaded systemd-journal-logger v2.2.2
Downloaded gix-prompt v0.15.0
Downloaded fastrand v2.3.0
Downloaded fnv v1.0.7
Downloaded gix-shallow v0.12.0
Downloaded referencing v0.30.0
Downloaded snapbox-macros v1.1.0
Downloaded sval_ref v2.17.0
Downloaded sha1 v0.10.6
Downloaded rand_xorshift v0.4.0
Downloaded sval v2.17.0
Downloaded gix-quote v0.7.1
Downloaded derive_more v2.1.1
Downloaded gix-glob v0.26.0
Downloaded socks5-client v0.4.3
Downloaded signal-hook v0.3.18
Downloaded ref-cast-impl v1.0.25
Downloaded siphasher v0.3.11
Downloaded gix-hashtable v0.15.0
Downloaded ghash v0.5.1
Downloaded document-features v0.2.12
Downloaded same-file v1.0.6
Downloaded test-log-macros v0.2.19
Downloaded heck v0.5.0
Downloaded curve25519-dalek-derive v0.1.1
Downloaded ctr v0.9.2
Downloaded colorchoice v1.0.5
Downloaded gix-validate v0.11.1
Downloaded env_filter v1.0.0
Downloaded generic-array v0.14.7
Downloaded gix-chunk v0.7.1
Downloaded matchers v0.2.0
Downloaded dunce v1.0.5
Downloaded gix-actor v0.41.0
Downloaded errno v0.3.14
Downloaded form_urlencoded v1.2.2
Downloaded dyn-clone v1.0.20
Downloaded gix-revision v0.45.0
Downloaded gix-revwalk v0.31.0
Downloaded displaydoc v0.2.5
Downloaded ecdsa v0.16.9
Downloaded ed25519 v1.5.3
Downloaded gix-packetline v0.21.5
Downloaded gix-refspec v0.41.0
Downloaded scrypt v0.11.0
Downloaded gix-lock v23.0.0
Downloaded shell-words v1.1.1
Downloaded gix-hash v0.25.0
Downloaded crossbeam-utils v0.8.21
Downloaded either v1.15.0
Downloaded structured-logger v1.0.5
Downloaded tree-sitter-json v0.24.8
Downloaded outref v0.5.2
Downloaded potential_utf v0.1.4
Downloaded gix-config-value v0.18.0
Downloaded gix-credentials v0.38.0
Downloaded secrecy v0.10.3
Downloaded convert_case v0.10.0
Downloaded ssh-cipher v0.2.0
Downloaded rustc_version v0.4.1
Downloaded serde_fmt v1.1.0
Downloaded email_address v0.2.9
Downloaded erased-serde v0.4.10
Downloaded zerofrom-derive v0.1.6
Downloaded ref-cast v1.0.25
Downloaded stable_deref_trait v1.2.1
Downloaded const-str v0.4.3
Downloaded ec25519 v0.1.0
Downloaded strsim v0.11.1
Downloaded find-msvc-tools v0.1.9
Downloaded nonempty v0.9.0
Downloaded rfc6979 v0.4.0
Downloaded salsa20 v0.10.2
Downloaded semver v1.0.27
Downloaded shlex v1.3.0
Downloaded signature v1.6.4
Downloaded signature v2.2.0
Downloaded sqlite3-sys v0.18.0
Downloaded streaming-iterator v0.1.9
Downloaded subtle v2.6.1
Downloaded sval_dynamic v2.17.0
Downloaded sval_serde v2.17.0
Downloaded synstructure v0.13.2
Downloaded test-log v0.2.19
Downloaded thiserror-impl v1.0.69
Downloaded borrow-or-share v0.2.4
Downloaded escargot v0.5.15
Downloaded gix-error v0.2.3
Downloaded gix-fs v0.21.1
Downloaded gix-ref v0.63.0
Downloaded gix-tempfile v23.0.0
Downloaded ppv-lite86 v0.2.21
Downloaded uuid-simd v0.8.0
Downloaded bcrypt-pbkdf v0.10.0
Downloaded bytecount v0.6.9
Downloaded console v0.16.3
Downloaded diff v0.1.13
Downloaded gix-features v0.48.0
Downloaded iana-time-zone v0.1.65
Downloaded spin v0.9.9
Downloaded crc32fast v1.5.0
Downloaded thiserror v2.0.18
Downloaded thiserror-impl v2.0.18
Downloaded pem-rfc7468 v0.7.0
Downloaded tree-sitter-language v0.1.7
Downloaded base16ct v0.2.0
Downloaded signal-hook-registry v1.4.8
Downloaded sha2 v0.10.9
Downloaded sem_safe v0.2.1
Downloaded cbc v0.1.2
Downloaded gix-date v0.15.3
Downloaded getrandom v0.2.17
Downloaded env_logger v0.11.9
Downloaded value-bag-serde1 v1.12.0
Downloaded rand_core v0.6.4
Downloaded rustc-demangle v0.1.27
Downloaded colored v2.2.0
Downloaded pkcs8 v0.10.2
Downloaded simd-adler32 v0.3.8
Downloaded rusty-fork v0.3.1
Downloaded sec1 v0.7.3
Downloaded zmij v1.0.21
Downloaded num-complex v0.4.6
Downloaded gix-odb v0.80.0
Downloaded sval_nested v2.17.0
Downloaded thread_local v1.1.9
Downloaded serde-untagged v0.1.9
Downloaded sqlite v0.37.0
Downloaded sval_fmt v2.17.0
Downloaded signals_receipts v0.2.5
Downloaded hex-literal v1.1.0
Downloaded schemars_derive v1.2.1
Downloaded scopeguard v1.2.0
Downloaded serde_core v1.0.228
Downloaded idna_adapter v1.2.1
Downloaded tempfile v3.27.0
Downloaded anstream v0.6.21
Downloaded anstream v1.0.0
Downloaded bit-set v0.8.0
Downloaded gix-diff v0.63.0
Downloaded keccak v0.1.6
Downloaded getrandom v0.4.3
Downloaded getrandom v0.3.4
Downloaded zerovec-derive v0.11.2
Downloaded gix-protocol v0.61.0
Downloaded rs-release v0.1.11
Downloaded nu-ansi-term v0.50.3
Downloaded icu_normalizer v2.1.1
Downloaded icu_normalizer_data v2.1.1
Downloaded flate2 v1.1.9
Downloaded thiserror v1.0.69
Downloaded pastey v0.2.1
Downloaded pbkdf2 v0.12.2
Downloaded crossterm v0.29.0
Downloaded fancy-regex v0.14.0
Downloaded serde_derive_internals v0.29.1
Downloaded universal-hash v0.5.1
Downloaded rustversion v1.0.22
Downloaded sval_buffer v2.17.0
Downloaded primeorder v0.13.6
Downloaded num-integer v0.1.46
Downloaded anstyle-query v1.1.5
Downloaded smallvec v1.15.1
Downloaded ryu v1.0.23
Downloaded itoa v1.0.17
Downloaded blowfish v0.9.1
Downloaded opaque-debug v0.3.1
Downloaded rand_core v0.9.5
Downloaded parking_lot v0.12.5
Downloaded unicode-ident v1.0.24
Downloaded elliptic-curve v0.13.8
Downloaded tree-sitter-css v0.23.2
Downloaded ssh-agent-lib v0.6.0
Downloaded sharded-slab v0.1.7
Downloaded snapbox v1.2.2
Downloaded gix-url v0.36.0
Downloaded pin-project-lite v0.2.17
Downloaded toml_writer v1.0.7+spec-1.1.0
Downloaded tree-sitter-toml-ng v0.6.0
Downloaded jobserver v0.1.34
Downloaded icu_properties v2.1.2
Downloaded serde_derive v1.0.228
Downloaded num-rational v0.4.2
Downloaded gix-trace v0.1.21
Downloaded heapless v0.8.0
Downloaded miniz_oxide v0.8.9
Downloaded tinystr v0.8.2
Downloaded icu_collections v2.1.1
Downloaded anstyle-parse v1.0.0
Downloaded icu_locale_core v2.1.1
Downloaded value-bag v1.12.0
Downloaded anstyle v1.0.14
Downloaded walkdir v2.5.0
Downloaded timeago v0.4.2
Downloaded litrs v1.0.0
Downloaded memmap2 v0.9.10
Downloaded multibase v0.9.2
Downloaded nonempty v0.12.0
Downloaded socket2 v0.5.10
Downloaded serde v1.0.228
Downloaded unarray v0.1.4
Downloaded yoke v0.8.1
Downloaded polyval v0.6.2
Downloaded hmac v0.12.1
Downloaded toml_datetime v0.7.5+spec-1.1.0
Downloaded fraction v0.15.3
Downloaded amplify_syn v2.0.1
Downloaded byteorder v1.5.0
Downloaded typeid v1.0.3
Downloaded similar v3.1.1
Downloaded noise-framework v0.4.1
Downloaded gix-pack v0.70.0
Downloaded anstyle-parse v0.2.7
Downloaded lock_api v0.4.14
Downloaded base-x v0.2.11
Downloaded normalize-line-endings v0.3.0
Downloaded version_check v0.9.5
Downloaded phf v0.11.3
Downloaded anyhow v1.0.102
Downloaded num v0.4.3
Downloaded tinyvec v1.11.0
Downloaded base256emoji v1.0.2
Downloaded qcheck v1.0.0
Downloaded ed25519-dalek v2.2.0
Downloaded value-bag-sval2 v1.12.0
Downloaded hash32 v0.3.1
Downloaded ssh-key v0.6.7
Downloaded block-buffer v0.10.4
Downloaded utf8_iter v1.0.4
Downloaded block-padding v0.3.3
Downloaded inout v0.1.4
Downloaded icu_provider v2.1.1
Downloaded tinyvec_macros v0.1.1
Downloaded bit-vec v0.8.0
Downloaded unicode-display-width v0.3.0
Downloaded aead v0.5.2
Downloaded percent-encoding v2.3.2
Downloaded adler2 v2.0.1
Downloaded lazy_static v1.5.0
Downloaded wait-timeout v0.2.1
Downloaded unit-prefix v0.5.2
Downloaded utf8parse v0.2.2
Downloaded gix-utils v0.3.2
Downloaded num-cmp v0.1.0
Downloaded yoke-derive v0.8.1
Downloaded amplify v4.9.0
Downloaded tracing-log v0.2.0
Downloaded emojis v0.6.4
Downloaded cfg-if v1.0.4
Downloaded zerofrom v0.1.6
Downloaded autocfg v1.5.0
Downloaded bitflags v2.11.0
Downloaded phf_shared v0.11.3
Downloaded vsimd v0.8.0
Downloaded gix-traverse v0.57.0
Downloaded group v0.13.0
Downloaded base32 v0.4.0
Downloaded is_terminal_polyfill v1.70.2
Downloaded arc-swap v1.9.1
Downloaded match-lookup v0.1.2
Downloaded once_cell v1.21.4
Downloaded pretty_assertions v1.4.1
Downloaded zerotrie v0.2.3
Downloaded zeroize v1.9.0
Downloaded prodash v31.0.0
Downloaded pkg-config v0.3.32
Downloaded base64ct v1.8.3
Downloaded typenum v1.20.1
Downloaded indexmap v2.13.0
Downloaded chacha20 v0.9.1
Downloaded log v0.4.29
Downloaded writeable v0.6.2
Downloaded pkcs1 v0.7.5
Downloaded humantime v2.3.0
Downloaded human-panic v2.0.6
Downloaded tree-sitter-highlight v0.24.7
Downloaded bytesize v2.3.1
Downloaded lexopt v0.3.2
Downloaded tree-sitter-html v0.23.2
Downloaded num-iter v0.1.45
Downloaded amplify_num v0.5.3
Downloaded tracing-core v0.1.36
Downloaded poly1305 v0.8.0
Downloaded amplify_derive v4.0.1
Downloaded ascii v1.1.0
Downloaded ahash v0.8.12
Downloaded zerovec v0.11.5
Downloaded litemap v0.8.1
Downloaded proc-macro2 v1.0.106
Downloaded maybe-async v0.2.10
Downloaded mio v1.1.1
Downloaded parking_lot_core v0.9.12
Downloaded unicode-normalization v0.1.25
Downloaded bytes v1.11.1
Downloaded num-traits v0.2.19
Downloaded tree-sitter-go v0.23.4
Downloaded p256 v0.13.2
Downloaded uuid v1.22.0
Downloaded gix-transport v0.57.0
Downloaded serde_json v1.0.149
Downloaded regex v1.12.3
Downloaded indicatif v0.18.4
Downloaded aes v0.8.4
Downloaded chacha20poly1305 v0.10.1
Downloaded url v2.5.8
Downloaded base64 v0.22.1
Downloaded backtrace v0.3.76
Downloaded toml v0.9.12+spec-1.1.0
Downloaded yansi v1.0.1
Downloaded num-bigint-dig v0.8.6
Downloaded unicode-segmentation v1.12.0
Downloaded libm v0.2.16
Downloaded inquire v0.9.4
Downloaded memchr v2.8.0
Downloaded aes-gcm v0.10.3
Downloaded jiff-static v0.2.23
Downloaded cc v1.2.57
Downloaded base64 v0.21.7
Downloaded icu_properties_data v2.1.2
Downloaded num-bigint v0.4.6
Downloaded hashbrown v0.16.1
Downloaded idna v1.1.0
Downloaded p521 v0.13.3
Downloaded itertools v0.14.0
Downloaded gimli v0.32.3
Downloaded git2 v0.21.0
Downloaded p384 v0.13.1
Downloaded jsonschema v0.30.0
Downloaded sysinfo v0.37.2
Downloaded aho-corasick v1.1.4
Downloaded tree-sitter v0.24.7
Downloaded curve25519-dalek v4.1.3
Downloaded vcpkg v0.2.15
Downloaded syn v1.0.109
Downloaded syn v2.0.117
Downloaded proptest v1.10.0
Downloaded tree-sitter-md v0.3.2
Downloaded zlib-rs v0.6.5
Downloaded tree-sitter-rust v0.23.3
Downloaded tree-sitter-python v0.23.6
Downloaded tracing v0.1.44
Downloaded portable-atomic v1.13.1
Downloaded tree-sitter-typescript v0.23.2
Downloaded tracing-subscriber v0.3.23
Downloaded libc v0.2.183
Downloaded tree-sitter-c v0.23.4
Downloaded bstr v1.12.1
Downloaded unicode-width v0.2.2
Downloaded regex-syntax v0.8.10
Downloaded zerocopy v0.8.42
Downloaded rustix v1.1.4
Downloaded bloomy v1.2.0
Downloaded object v0.37.3
Downloaded tree-sitter-bash v0.23.3
Downloaded regex-automata v0.4.14
Downloaded tree-sitter-ruby v0.23.1
Downloaded jiff v0.2.23
Downloaded sha3 v0.10.8
Downloaded sha1-checked v0.10.0
Downloaded tokio v1.50.0
Downloaded libz-sys v1.1.25
Downloaded libgit2-sys v0.18.4+1.9.3
Downloaded sqlite3-src v0.7.0
Downloaded linux-raw-sys v0.12.1
Compiling libc v0.2.183
Compiling proc-macro2 v1.0.106
Compiling quote v1.0.45
Compiling unicode-ident v1.0.24
Compiling serde_core v1.0.228
Checking cfg-if v1.0.4
Compiling serde v1.0.228
Compiling version_check v0.9.5
Compiling generic-array v0.14.7
Checking typenum v1.20.1
Compiling syn v2.0.117
Checking getrandom v0.2.17
Checking rand_core v0.6.4
Checking memchr v2.8.0
Compiling shlex v1.3.0
Compiling jobserver v0.1.34
Compiling find-msvc-tools v0.1.9
Checking subtle v2.6.1
Checking const-oid v0.9.6
Compiling cc v1.2.57
Checking smallvec v1.15.1
Checking regex-syntax v0.8.10
Checking aho-corasick v1.1.4
Checking cpufeatures v0.2.17
Compiling thiserror v2.0.18
Checking fastrand v2.3.0
Compiling parking_lot_core v0.9.12
Checking regex-automata v0.4.14
Checking scopeguard v1.2.0
Checking lock_api v0.4.14
Checking bitflags v2.11.0
Checking parking_lot v0.12.5
Checking stable_deref_trait v1.2.1
Compiling typeid v1.0.3
Compiling erased-serde v0.4.10
Checking itoa v1.0.17
Checking gix-trace v0.1.21
Checking tinyvec_macros v0.1.1
Checking tinyvec v1.11.0
Checking serde_fmt v1.1.0
Checking hashbrown v0.16.1
Checking unicode-normalization v0.1.25
Checking value-bag-serde1 v1.12.0
Checking byteorder v1.5.0
Checking value-bag v1.12.0
Checking gix-utils v0.3.2
Compiling crc32fast v1.5.0
Checking log v0.4.29
Checking bstr v1.12.1
Checking same-file v1.0.6
Checking prodash v31.0.0
Checking walkdir v2.5.0
Compiling serde_derive v1.0.228
Compiling thiserror-impl v2.0.18
Checking zlib-rs v0.6.5
Checking gix-validate v0.11.1
Compiling heapless v0.8.0
Compiling pkg-config v0.3.32
Compiling autocfg v1.5.0
Compiling libm v0.2.16
Compiling getrandom v0.4.3
Checking gix-path v0.12.0
Compiling num-traits v0.2.19
Checking gix-features v0.48.0
Checking hash32 v0.3.1
Compiling rustix v1.1.4
Checking linux-raw-sys v0.12.1
Checking faster-hex v0.10.0
Compiling zerocopy v0.8.42
Compiling zmij v1.0.21
Checking equivalent v1.0.2
Compiling serde_json v1.0.149
Checking indexmap v2.13.0
Checking zeroize v1.9.0
Checking once_cell v1.21.4
Checking crypto-common v0.1.7
Checking block-buffer v0.10.4
Compiling ref-cast v1.0.25
Checking digest v0.10.7
Checking block-padding v0.3.3
Checking sha1 v0.10.6
Checking sha1-checked v0.10.0
Checking gix-hash v0.25.0
Compiling ref-cast-impl v1.0.25
Checking inout v0.1.4
Checking sha2 v0.10.9
Compiling vcpkg v0.2.15
Checking dyn-clone v1.0.20
Checking cipher v0.4.4
Checking tempfile v3.27.0
Compiling serde_derive_internals v0.29.1
Checking der v0.7.10
Compiling libz-sys v1.1.25
Checking ppv-lite86 v0.2.21
Compiling libgit2-sys v0.18.4+1.9.3
Checking spin v0.9.9
Checking lazy_static v1.5.0
Compiling schemars_derive v1.2.1
Checking rand_chacha v0.3.1
Compiling syn v1.0.109
Checking rand v0.8.5
Compiling tree-sitter-language v0.1.7
Checking hmac v0.12.1
Checking universal-hash v0.5.1
Checking num-integer v0.1.46
Checking opaque-debug v0.3.1
Checking spki v0.7.3
Checking signature v2.2.0
Checking ff v0.13.1
Checking base16ct v0.2.0
Checking sec1 v0.7.3
Checking schemars v1.2.1
Checking group v0.13.0
Checking crypto-bigint v0.5.5
Compiling data-encoding v2.10.0
Compiling data-encoding-macro-internal v0.1.17
Checking elliptic-curve v0.13.8
Compiling amplify_syn v2.0.1
Checking num-iter v0.1.45
Checking aead v0.5.2
Compiling match-lookup v0.1.2
Compiling semver v1.0.27
Checking const-str v0.4.3
Checking signature v1.6.4
Checking base256emoji v1.0.2
Checking ed25519 v1.5.3
Checking data-encoding-macro v0.1.19
Compiling amplify_derive v4.0.1
Compiling rustc_version v0.4.1
Checking poly1305 v0.8.0
Checking rfc6979 v0.4.0
Checking qcheck v1.0.0
Checking chacha20 v0.9.1
Checking gix-error v0.2.3
Checking ascii v1.1.0
Checking amplify_num v0.5.3
Checking base-x v0.2.11
Checking multibase v0.9.2
Checking ecdsa v0.16.9
Compiling curve25519-dalek v4.1.3
Checking ec25519 v0.1.0
Checking primeorder v0.13.6
Checking amplify v4.9.0
Checking polyval v0.6.2
Checking base64ct v1.8.3
Compiling num-bigint-dig v0.8.6
Checking ghash v0.5.1
Checking pem-rfc7468 v0.7.0
Checking pkcs8 v0.10.2
Checking cyphergraphy v0.3.1
Checking pbkdf2 v0.12.2
Checking aes v0.8.4
Checking ctr v0.9.2
Checking radicle-git-ref-format v0.2.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-git-ref-format)
Compiling sqlite3-src v0.7.0
Compiling curve25519-dalek-derive v0.1.1
Compiling synstructure v0.13.2
Checking keccak v0.1.6
Checking sha3 v0.10.8
Checking aes-gcm v0.10.3
Checking pkcs1 v0.7.5
Checking ssh-encoding v0.2.0
Checking ed25519 v2.2.3
Checking cbc v0.1.2
Checking blowfish v0.9.1
Checking percent-encoding v2.3.2
Checking base32 v0.4.0
Checking cypheraddr v0.4.1
Checking rsa v0.9.10
Checking bcrypt-pbkdf v0.10.0
Checking ssh-cipher v0.2.0
Checking ed25519-dalek v2.2.0
Compiling zerofrom-derive v0.1.6
Checking p521 v0.13.3
Checking p256 v0.13.2
Checking p384 v0.13.1
Checking chacha20poly1305 v0.10.1
Checking noise-framework v0.4.1
Checking ssh-key v0.6.7
Checking zerofrom v0.1.6
Checking socks5-client v0.4.3
Compiling yoke-derive v0.8.1
Checking secrecy v0.10.3
Checking ssh-agent-lib v0.6.0
Checking cyphernet v0.5.4
Checking nonempty v0.9.0
Checking anstyle-query v1.1.5
Checking utf8parse v0.2.2
Checking yoke v0.8.1
Checking jiff v0.2.23
Compiling zerovec-derive v0.11.2
Checking zerovec v0.11.5
Checking radicle-localtime v0.1.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-localtime)
Compiling displaydoc v0.2.5
Checking errno v0.3.14
Checking anstyle v1.0.14
Checking gix-date v0.15.3
Checking colorchoice v1.0.5
Checking base64 v0.21.7
Checking is_terminal_polyfill v1.70.2
Checking gix-actor v0.41.0
Checking gix-hashtable v0.15.0
Checking siphasher v1.0.2
Checking gix-object v0.60.0
Checking radicle-dag v0.10.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-dag)
Checking memmap2 v0.9.10
Checking nonempty v0.12.0
Checking tinystr v0.8.2
Checking gix-chunk v0.7.1
Checking writeable v0.6.2
Compiling radicle v0.25.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle)
Checking litemap v0.8.1
Checking icu_locale_core v2.1.1
Checking gix-commitgraph v0.37.0
Checking zerotrie v0.2.3
Checking potential_utf v0.1.4
Checking anstyle-parse v1.0.0
Checking serde-untagged v0.1.9
Checking bytesize v2.3.1
Checking fast-glob v0.3.3
Compiling icu_properties_data v2.1.2
Compiling icu_normalizer_data v2.1.1
Checking dunce v1.0.5
Checking anstream v1.0.0
Checking icu_collections v2.1.1
Checking icu_provider v2.1.1
Checking gix-revwalk v0.31.0
Checking gix-fs v0.21.1
Checking mio v1.1.1
Checking sem_safe v0.2.1
Checking simd-adler32 v0.3.8
Checking adler2 v2.0.1
Checking signals_receipts v0.2.5
Checking miniz_oxide v0.8.9
Checking gix-tempfile v23.0.0
Checking gix-quote v0.7.1
Checking icu_properties v2.1.2
Checking icu_normalizer v2.1.1
Checking shell-words v1.1.1
Checking iana-time-zone v0.1.65
Compiling signal-hook v0.3.18
Checking either v1.15.0
Compiling unicode-segmentation v1.12.0
Checking idna_adapter v1.2.1
Checking chrono v0.4.44
Compiling convert_case v0.10.0
Checking gix-command v0.9.0
Checking radicle-signals v0.12.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-signals)
Checking signal-hook-registry v1.4.8
Checking colored v2.2.0
Compiling rustversion v1.0.22
Compiling object v0.37.3
Compiling getrandom v0.3.4
Checking utf8_iter v1.0.4
Checking idna v1.1.0
Compiling derive_more-impl v2.1.1
Checking gix-lock v23.0.0
Checking gix-url v0.36.0
Checking gix-config-value v0.18.0
Checking gix-sec v0.14.0
Compiling litrs v1.0.0
Compiling portable-atomic v1.13.1
Checking unicode-width v0.2.2
Checking gimli v0.32.3
Compiling thiserror v1.0.69
Compiling document-features v0.2.12
Checking gix-prompt v0.15.0
Checking derive_more v2.1.1
Checking signal-hook-mio v0.2.5
Checking addr2line v0.25.1
Checking radicle-log v0.2.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-log)
Checking gix-traverse v0.57.0
Checking gix-revision v0.45.0
Checking gix-diff v0.63.0
Checking anstyle-parse v0.2.7
Checking gix-packetline v0.21.5
Checking gix-glob v0.26.0
Compiling thiserror-impl v1.0.69
Checking rustc-demangle v0.1.27
Checking backtrace v0.3.76
Checking gix-refspec v0.41.0
Checking gix-transport v0.57.0
Checking anstream v0.6.21
Checking gix-pack v0.70.0
Checking arc-swap v1.9.1
Checking crossterm v0.29.0
Checking gix-credentials v0.38.0
Checking console v0.16.3
Checking gix-shallow v0.12.0
Checking gix-ref v0.63.0
Checking gix-negotiate v0.31.0
Checking form_urlencoded v1.2.2
Compiling maybe-async v0.2.10
Checking regex v1.12.3
Compiling tree-sitter v0.24.7
Checking unit-prefix v0.5.2
Checking indicatif v0.18.4
Checking gix-protocol v0.61.0
Checking url v2.5.8
Checking gix-odb v0.80.0
Checking inquire v0.9.4
Checking unicode-display-width v0.3.0
Checking uuid v1.22.0
Checking bytes v1.11.1
Checking snapbox-macros v1.1.0
Checking salsa20 v0.10.2
Checking siphasher v0.3.11
Compiling crossbeam-utils v0.8.21
Checking streaming-iterator v0.1.9
Checking strsim v0.11.1
Checking similar v3.1.1
Checking clap_lex v1.1.0
Compiling heck v0.5.0
Checking normalize-line-endings v0.3.0
Compiling clap_derive v4.6.0
Checking snapbox v1.2.2
Checking clap_builder v4.6.0
Checking bloomy v1.2.0
Checking scrypt v0.11.0
Checking systemd-journal-logger v2.2.2
Compiling tree-sitter-ruby v0.23.1
Compiling tree-sitter-python v0.23.6
Compiling tree-sitter-c v0.23.4
Compiling tree-sitter-go v0.23.4
Compiling tree-sitter-rust v0.23.3
Compiling tree-sitter-toml-ng v0.6.0
Compiling tree-sitter-bash v0.23.3
Compiling tree-sitter-css v0.23.2
Compiling tree-sitter-json v0.24.8
Compiling tree-sitter-typescript v0.23.2
Compiling tree-sitter-md v0.3.2
Compiling tree-sitter-html v0.23.2
Checking toml_datetime v0.7.5+spec-1.1.0
Checking serde_spanned v1.0.4
Compiling anyhow v1.0.102
Checking pin-project-lite v0.2.17
Checking bit-vec v0.8.0
Checking toml_writer v1.0.7+spec-1.1.0
Checking bit-set v0.8.0
Checking toml v0.9.12+spec-1.1.0
Checking tokio v1.50.0
Checking sqlite3-sys v0.18.0
Checking sqlite v0.37.0
Checking radicle-crypto v0.19.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-crypto)
Checking clap v4.6.0
Checking rand_core v0.9.5
Checking sysinfo v0.37.2
Checking diff v0.1.13
Checking yansi v1.0.1
Compiling radicle-cli v0.23.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-cli)
Compiling radicle-node v0.21.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-node)
Checking pretty_assertions v1.4.1
Checking human-panic v2.0.6
Checking crossbeam-channel v0.5.15
Checking clap_complete v4.6.0
Checking structured-logger v1.0.5
Checking radicle-systemd v0.13.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-systemd)
Checking tree-sitter-highlight v0.24.7
Checking itertools v0.14.0
Checking socket2 v0.5.10
Compiling escargot v0.5.15
Checking rs-release v0.1.11
Checking lexopt v0.3.2
Checking timeago v0.4.2
Checking humantime v2.3.0
Checking wait-timeout v0.2.1
Checking fnv v1.0.7
Checking quick-error v1.2.3
Checking rusty-fork v0.3.1
Checking rand_chacha v0.9.0
Checking rand v0.9.2
Checking rand_xorshift v0.4.0
Compiling qcheck-macros v1.0.0
Checking num-bigint v0.4.6
Compiling ahash v0.8.12
Checking unarray v0.1.4
Checking proptest v1.10.0
Checking num-complex v0.4.6
Checking env_filter v1.0.0
Checking borrow-or-share v0.2.4
Checking fluent-uri v0.3.2
Checking num-rational v0.4.2
Checking num v0.4.3
Checking env_logger v0.11.9
Checking flate2 v1.1.9
Checking phf_shared v0.11.3
Compiling test-log-macros v0.2.19
Checking hex-literal v1.1.0
Checking outref v0.5.2
Checking vsimd v0.8.0
Compiling radicle-remote-helper v0.18.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-remote-helper)
Checking uuid-simd v0.8.0
Checking test-log v0.2.19
Checking phf v0.11.3
Checking referencing v0.30.0
Checking fraction v0.15.3
Checking fancy-regex v0.14.0
Checking email_address v0.2.9
Checking bytecount v0.6.9
Checking num-cmp v0.1.0
Checking base64 v0.22.1
Checking emojis v0.6.4
Compiling pastey v0.2.1
Checking jsonschema v0.30.0
Checking radicle-windows v0.1.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-windows)
Checking git2 v0.21.0
Checking radicle-oid v0.2.2 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-oid)
Checking radicle-git-metadata v0.2.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-git-metadata)
Checking radicle-term v0.19.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-term)
Checking radicle-core v0.4.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-core)
Checking radicle-cob v0.21.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-cob)
Checking radicle-surf v0.29.0 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-surf)
Checking radicle-cli-test v0.14.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-cli-test)
error[E0061]: this function takes 0 arguments but 7 arguments were supplied
--> crates/radicle/src/rad.rs:623:29
|
623 | let (rid, doc, _) = init(
| ^^^^
|
note: function defined here
--> crates/radicle/src/rad.rs:559:8
|
559 | fn init() {
| ^^^^
help: remove the extra arguments
|
624 - &repo,
625 - "acme".try_into().unwrap(),
626 - "Acme's repo",
627 - None,
628 - Visibility::default(),
629 - &signer,
630 - &storage,
631 - )
624 + )
|
error[E0599]: no method named `unwrap` found for unit type `()` in the current scope
--> crates/radicle/src/rad.rs:632:10
|
623 | let (rid, doc, _) = init(
| _____________________________-
624 | | &repo,
625 | | "acme".try_into().unwrap(),
626 | | "Acme's repo",
... |
632 | | .unwrap();
| |_________-^^^^^^
|
help: there is a method `wrap` with a similar name
|
632 - .unwrap();
632 + .wrap();
|
Checking radicle-fetch v0.21.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-fetch)
Checking radicle-schemars v0.9.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-schemars)
Checking radicle-protocol v0.9.1 (/96c9545b-f698-4e88-986a-49d537f839ae/w/crates/radicle-protocol)
Some errors have detailed explanations: E0061, E0599.
For more information about an error, try `rustc --explain E0061`.
error: could not compile `radicle` (lib test) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
Exit code: 101
{
"response": "finished",
"result": "failure"
}