From 03a4e19c9cab443b58a1b557d3d643440949667c Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 00:58:38 +0900 Subject: [PATCH 1/7] feat: Support forking repo before cloning --- Cargo.lock | 803 ++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 9 +- src/cmd/clone.rs | 47 ++- src/config.rs | 3 + src/main.rs | 1 + src/platform/github.rs | 66 ++++ src/platform/mod.rs | 79 ++++ 7 files changed, 987 insertions(+), 21 deletions(-) create mode 100644 src/platform/github.rs create mode 100644 src/platform/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 1e66a98..3fb49ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "0.7.20" @@ -26,18 +41,66 @@ version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "async-hofs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38b259e145ec72412cda6646eca167e3baf014ff9fdeb2dd8e6370456bb2f8" +dependencies = [ + "futures-core", + "pin-project", +] + +[[package]] +name = "async-trait" +version = "0.1.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.3", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" + [[package]] name = "base64" version = "0.21.0" @@ -136,6 +199,12 @@ version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + [[package]] name = "camino" version = "1.1.4" @@ -262,6 +331,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -388,13 +467,33 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.0", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", ] [[package]] @@ -408,6 +507,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.8.1" @@ -420,6 +525,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "errno" version = "0.2.8" @@ -456,15 +570,70 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ + "matches", "percent-encoding", ] +[[package]] +name = "futures-channel" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" + +[[package]] +name = "futures-sink" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" + +[[package]] +name = "futures-task" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" + +[[package]] +name = "futures-util" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -476,26 +645,43 @@ dependencies = [ "wasi", ] +[[package]] +name = "gh-config" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95d3f5016c6706e2d501eeb52d41f1865bb3e179b138366f20f979dfdd69e822" +dependencies = [ + "dirs 4.0.0", + "serde", + "serde_yaml", + "thiserror", +] + [[package]] name = "ghr" version = "0.3.4" dependencies = [ "anyhow", + "async-hofs", + "async-trait", "build-info", "build-info-build", "clap", "console", "dialoguer", - "dirs", + "dirs 5.0.0", + "gh-config", "git2", "indicatif", "itertools", "lazy_static", + "octocrab", "regex", "serde", "serde_regex", "serde_with", "tokio", + "tokio-stream", "toml", "tracing", "tracing-subscriber", @@ -503,6 +689,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + [[package]] name = "git2" version = "0.16.1" @@ -524,6 +716,25 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "h2" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -557,6 +768,93 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyperx" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5617e92fc2f2501c3e2bc6ce547cad841adba2bae5b921c7e52510beca6d084c" +dependencies = [ + "base64 0.13.1", + "bytes", + "http", + "httpdate", + "language-tags", + "mime", + "percent-encoding", + "unicase", +] + [[package]] name = "iana-time-zone" version = "0.1.53" @@ -589,10 +887,11 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" dependencies = [ + "matches", "unicode-bidi", "unicode-normalization", ] @@ -640,6 +939,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "ipnet" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146" + [[package]] name = "is-terminal" version = "0.4.4" @@ -685,6 +990,26 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "8.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" +dependencies = [ + "base64 0.21.0", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + [[package]] name = "lazy_static" version = "1.4.0" @@ -781,12 +1106,63 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -843,12 +1219,72 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "octocrab" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f21c2c98d2c7556e4bbacac59eb3d7449ef6a9b0f14d3aa348f692f4e851f6" +dependencies = [ + "arc-swap", + "async-trait", + "base64 0.20.0", + "bytes", + "cfg-if", + "chrono", + "either", + "hyperx", + "jsonwebtoken", + "once_cell", + "reqwest", + "secrecy", + "serde", + "serde_json", + "serde_path_to_error", + "snafu", + "url", +] + [[package]] name = "once_cell" version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +[[package]] +name = "openssl" +version = "0.10.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "518915b97df115dd36109bfa429a48b8f737bd05508cf9588977b599648926d2" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "openssl-probe" version = "0.1.5" @@ -866,9 +1302,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.81" +version = "0.9.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176be2629957c157240f68f61f2d0053ad3a4ecfdd9ebf1e6521d18d9635cf67" +checksum = "666416d899cf077260dac8698d60a60b435a46d57e82acb1be3d0dad87284e5b" dependencies = [ "autocfg", "cc", @@ -899,11 +1335,40 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] name = "pin-project-lite" @@ -911,6 +1376,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.26" @@ -1023,6 +1494,64 @@ version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +[[package]] +name = "reqwest" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949" +dependencies = [ + "base64 0.21.0", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1061,12 +1590,53 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "scratch" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.17" @@ -1107,6 +1677,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0" +dependencies = [ + "serde", +] + [[package]] name = "serde_regex" version = "1.1.0" @@ -1126,6 +1705,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "2.3.1" @@ -1154,6 +1745,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "serde_yaml" +version = "0.9.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82e6c8c047aa50a7328632d067bcae6ef38772a79e28daf32f735e0e4f3dd10" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -1169,12 +1773,72 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "snafu" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0656e7e3ffb70f6c39b3c2a86332bb74aa3c679da781642590f3c1118c5045" +dependencies = [ + "backtrace", + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "strsim" version = "0.10.0" @@ -1304,8 +1968,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg", + "bytes", + "libc", + "memchr", + "mio", "num_cpus", "pin-project-lite", + "socket2", "tokio-macros", "windows-sys 0.45.0", ] @@ -1321,6 +1990,41 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml" version = "0.7.3" @@ -1355,6 +2059,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.37" @@ -1417,6 +2127,21 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.12" @@ -1444,15 +2169,28 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unsafe-libyaml" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad2024452afd3874bf539695e04af6732ba06517424dbf958fdb16a01f3bef6c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" -version = "2.3.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "22fe195a4f217c25b25cb5058ced57059824a678474874038dc88d211bf508d3" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -1483,6 +2221,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1514,6 +2262,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.84" @@ -1543,6 +2303,16 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1664,6 +2434,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "xz2" version = "0.1.7" diff --git a/Cargo.toml b/Cargo.toml index c810e47..ec7728a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,8 @@ authors = [ [dependencies] anyhow = "1.0" +async-hofs = "0.1.1" +async-trait = "0.1.67" build-info = "0.0.30" clap = { version = "4.1", features = ["derive"] } console = "0.15.2" @@ -28,15 +30,20 @@ serde = { version = "1.0", features = ["derive"] } serde_regex = "1.1" serde_with = "2.3" tokio = { version = "1.26", features = ["macros", "rt-multi-thread"] } +tokio-stream = "0.1.12" toml = "0.7.2" tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } url = "2.3" walkdir = "2.3" +gh-config = { version = "0.2.1", optional = true } +octocrab = { version = "0.18.1", optional = true } + [build-dependencies] build-info-build = "0.0.30" [features] -default = [] +default = ["github"] vendored = ["git2/vendored-libgit2", "git2/vendored-openssl"] +github = ["gh-config", "octocrab"] diff --git a/src/cmd/clone.rs b/src/cmd/clone.rs index 6987a04..47c937f 100644 --- a/src/cmd/clone.rs +++ b/src/cmd/clone.rs @@ -1,10 +1,12 @@ use std::path::PathBuf; -use anyhow::Result; +use anyhow::{anyhow, Result}; +use async_hofs::iter::AsyncMapExt; use clap::Parser; use console::style; use git2::Repository; use itertools::Itertools; +use tokio_stream::StreamExt; use tracing::info; use crate::config::Config; @@ -19,6 +21,10 @@ pub struct Cmd { /// URL or pattern of the repository to clone. repo: Vec, + /// Forks the repository in the specified owner (organisation) and clones the forked repo. + #[clap(long)] + fork: Option>, + /// Clones their submodules recursively. #[clap(short, long)] recursive: bool, @@ -37,11 +43,17 @@ impl Cmd { let root = Root::find()?; let config = Config::load_from(&root)?; + let urls = self + .repo + .iter() + .async_map(|repo| self.url(&config, repo)) + .collect::>>() + .await?; + let repo: Vec = Spinner::new("Cloning the repository...") .spin_while(|| async move { - self.repo - .iter() - .map(|repo| self.clone(&root, &config, repo)) + urls.into_iter() + .map(|url| self.clone(&root, &config, url)) .try_collect() }) .await?; @@ -76,16 +88,35 @@ impl Cmd { Ok(()) } - fn clone(&self, root: &Root, config: &Config, repo: &str) -> Result { - let url = Url::from_str(repo, &config.patterns, config.defaults.owner.as_deref())?; + async fn url(&self, config: &Config, repo: &str) -> Result { + let mut url = Url::from_str(repo, &config.patterns, config.defaults.owner.as_deref())?; + + if let Some(owner) = &self.fork { + info!("Forking from '{}'", url.to_string()); + + let platform = config + .platforms + .find(&url) + .ok_or_else(|| anyhow!("Could not find a platform to fork on."))? + .try_into_platform()?; + + url = Url::from_str( + &platform.fork(&url, owner.clone()).await?, + &config.patterns, + config.defaults.owner.as_deref(), + )?; + } + + Ok(url) + } + + fn clone(&self, root: &Root, config: &Config, url: Url) -> Result { let path = PathBuf::from(Path::resolve(root, &url)); let profile = config .rules .resolve(&url) .and_then(|r| config.profiles.resolve(&r.profile)); - info!("Cloning from '{}'", url.to_string()); - config.git.strategy.clone.clone_repository( url, &path, diff --git a/src/config.rs b/src/config.rs index 5bc6fa9..b4c30ed 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,7 @@ use serde::Deserialize; use crate::application::Applications; use crate::git::Config as GitConfig; +use crate::platform::Config as PlatformConfig; use crate::profile::Profiles; use crate::root::Root; use crate::rule::Rules; @@ -23,6 +24,8 @@ pub struct Config { #[serde(default)] pub git: GitConfig, #[serde(default)] + pub platforms: PlatformConfig, + #[serde(default)] pub patterns: Patterns, #[serde(default)] pub profiles: Profiles, diff --git a/src/main.rs b/src/main.rs index f5c8a20..96dd30a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod config; mod console; mod git; mod path; +mod platform; mod profile; mod repository; mod root; diff --git a/src/platform/github.rs b/src/platform/github.rs new file mode 100644 index 0000000..3cf3bd3 --- /dev/null +++ b/src/platform/github.rs @@ -0,0 +1,66 @@ +use anyhow::{anyhow, Result}; +use async_trait::async_trait; +use gh_config::{Hosts, GITHUB_COM}; +use octocrab::Octocrab; +use serde::Deserialize; + +use crate::platform::{Fork, Platform, PlatformInit}; +use crate::url::Url; + +#[derive(Debug, Deserialize)] +pub struct Config { + pub(super) host: String, +} + +impl Default for Config { + fn default() -> Self { + Self { + host: GITHUB_COM.to_string(), + } + } +} + +pub struct GitHub { + client: Octocrab, +} + +impl PlatformInit for GitHub { + type Config = Config; + + fn init(config: &Config) -> Result { + let token = Hosts::load()? + .get(&config.host) + .ok_or_else(|| { + anyhow!( + "gh CLI does not have any token for github.com. Run `gh auth login` and retry." + ) + })? + .oauth_token + .clone(); + + Ok(Self { + client: Octocrab::builder().personal_token(token).build()?, + }) + } +} + +impl Platform for GitHub {} + +#[async_trait] +impl Fork for GitHub { + async fn fork(&self, url: &Url, owner: Option) -> Result { + let request = self.client.repos(&url.owner, &url.repo); + let request = match owner { + Some(o) => request.create_fork().organization(o), + _ => request.create_fork(), + }; + + Ok(request + .send() + .await? + .html_url + .as_ref() + .ok_or_else(|| anyhow!("GitHub API did not return HTML URL for the repository."))? + .to_string()) + } +} diff --git a/src/platform/mod.rs b/src/platform/mod.rs new file mode 100644 index 0000000..7c294d5 --- /dev/null +++ b/src/platform/mod.rs @@ -0,0 +1,79 @@ +mod github; + +use std::result::Result as StdResult; + +use anyhow::Result; +use async_trait::async_trait; +use serde::Deserialize; +use std::collections::HashMap; + +use crate::url::Url; + +#[async_trait] +pub trait Fork { + async fn fork(&self, url: &Url, owner: Option) -> Result; +} + +pub trait PlatformInit: Sized { + type Config; + + fn init(config: &Self::Config) -> Result; +} + +pub trait Platform: Fork {} + +#[derive(Debug, Deserialize)] +#[serde(tag = "type")] +pub enum PlatformConfig { + #[cfg(feature = "github")] + GitHub(github::Config), +} + +impl PlatformConfig { + pub fn try_into_platform(&self) -> Result> { + self.try_into() + } + + fn host(&self) -> String { + match self { + #[cfg(feature = "github")] + Self::GitHub(c) => c.host.to_string(), + } + } +} + +impl TryInto> for &PlatformConfig { + type Error = anyhow::Error; + + fn try_into(self) -> StdResult, Self::Error> { + Ok(match self { + #[cfg(feature = "github")] + PlatformConfig::GitHub(c) => Box::new(github::GitHub::init(c)?), + }) + } +} + +#[derive(Debug, Deserialize)] +pub struct Config { + map: HashMap, +} + +impl Default for Config { + fn default() -> Self { + Self { + map: HashMap::from([ + #[cfg(feature = "github")] + ( + "github".to_string(), + PlatformConfig::GitHub(github::Config::default()), + ), + ]), + } + } +} + +impl Config { + pub fn find(&self, url: &Url) -> Option<&PlatformConfig> { + self.map.values().find(|c| c.host() == url.host.to_string()) + } +} From 22008c9a169cb2f0a7c077cef9c4f5d7a7e3e184 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:01:44 +0900 Subject: [PATCH 2/7] feat: Support GitHub Enterprise server --- src/platform/github.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platform/github.rs b/src/platform/github.rs index 3cf3bd3..c8c7e32 100644 --- a/src/platform/github.rs +++ b/src/platform/github.rs @@ -38,8 +38,13 @@ impl PlatformInit for GitHub { .oauth_token .clone(); + let mut builder = Octocrab::builder().personal_token(token); + if config.host != GITHUB_COM { + builder = builder.base_url(format!("https://{}/api/v3", &config.host))?; + } + Ok(Self { - client: Octocrab::builder().personal_token(token).build()?, + client: builder.build()?, }) } } From a4e88efb168b359ec51c539407029c2bbff23e13 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:03:08 +0900 Subject: [PATCH 3/7] chore: Add example for platforms config --- ghr.example.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ghr.example.toml b/ghr.example.toml index ec1f477..7a19135 100644 --- a/ghr.example.toml +++ b/ghr.example.toml @@ -12,6 +12,16 @@ owner = "siketyan" # 'Cli' is the default and only supported. strategy.clone = "Cli" +[platforms.github] +# Default configuration for GitHub.com. +type = "github" + +[platforms.ghe-acme] +# If you are using a GitHub Enterprise Server instance, +# Specify here to enable `--fork` working with repositories on the GHE server. +type = "github" +host = "ghe.example.com" + [[patterns]] # You can use additional patterns to specify where the repository is cloned from. # For details of regular expression syntax, see https://docs.rs/regex/latest/regex/index.html . From cb2af7a63043d535487ce25453ccf68493a4f117 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:07:10 +0900 Subject: [PATCH 4/7] fix: Add `Cloning from...` message again --- src/cmd/clone.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd/clone.rs b/src/cmd/clone.rs index 47c937f..54cf53d 100644 --- a/src/cmd/clone.rs +++ b/src/cmd/clone.rs @@ -53,7 +53,10 @@ impl Cmd { let repo: Vec = Spinner::new("Cloning the repository...") .spin_while(|| async move { urls.into_iter() - .map(|url| self.clone(&root, &config, url)) + .map(|url| { + info!("Cloning from '{}'", url.to_string()); + self.clone(&root, &config, url) + }) .try_collect() }) .await?; From ba3e71590017de097ff8cd9ae4d3a988b0cc3f89 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:08:04 +0900 Subject: [PATCH 5/7] fix: Trim spaces on git CLI output --- src/git/strategy/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git/strategy/cli.rs b/src/git/strategy/cli.rs index 6517cfe..341d2a3 100644 --- a/src/git/strategy/cli.rs +++ b/src/git/strategy/cli.rs @@ -27,7 +27,7 @@ impl CloneRepository for Cli { true => Ok(()), _ => Err(anyhow!( "Error occurred while cloning the repository: {}", - String::from_utf8_lossy(output.stderr.as_slice()), + String::from_utf8_lossy(output.stderr.as_slice()).trim(), )), } } From d45c7dc03914e29c50483cf7e4183924eba4db4a Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:10:30 +0900 Subject: [PATCH 6/7] fix: Add missing serde attributes --- src/platform/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 7c294d5..06147bc 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -26,6 +26,7 @@ pub trait Platform: Fork {} #[serde(tag = "type")] pub enum PlatformConfig { #[cfg(feature = "github")] + #[serde(rename = "github")] GitHub(github::Config), } @@ -55,6 +56,7 @@ impl TryInto> for &PlatformConfig { #[derive(Debug, Deserialize)] pub struct Config { + #[serde(flatten)] map: HashMap, } From ce48ee642ed3e63cc591c4f5f31d1dcb6c63326c Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Sun, 26 Mar 2023 01:16:40 +0900 Subject: [PATCH 7/7] fix: Fix github::Config requires host --- src/platform/github.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platform/github.rs b/src/platform/github.rs index c8c7e32..57ffe89 100644 --- a/src/platform/github.rs +++ b/src/platform/github.rs @@ -7,15 +7,20 @@ use serde::Deserialize; use crate::platform::{Fork, Platform, PlatformInit}; use crate::url::Url; +fn default_host() -> String { + GITHUB_COM.to_string() +} + #[derive(Debug, Deserialize)] pub struct Config { + #[serde(default = "default_host")] pub(super) host: String, } impl Default for Config { fn default() -> Self { Self { - host: GITHUB_COM.to_string(), + host: default_host(), } } }