Re-create this with the canvas option in Gemini 2.5 Pro web chat
```EOF Create a very minimal and simple tool written in rust which takes in a list of git URLs, and using the gitea api checks if the remote is already mirrored, and if not, then create a repo migration to gitea. I want to basically create a script which can be used to ensure a list of git repos are mirrord to a gitea server. The script should take in some command line arguments for; - an option to do a dry run, meaning do the check if the repo has to be mirrord, but do not initiate the actual migration - path to a TOML configuration file (also can be supplied via an ENV variable) The configuration file would have the following information; - an API key to be used when talking to the gitea instance we are migrating to - the url of the above gitea instance - a list of git URLs including an optional rename of the repo name - a list of URLs of another git server (gitea, if the API is the same then github, gitlab, etc) that includes the organization name or username. You would clone all repos under that organization/username. For example "https://github.com/hak8or" would be all repos owned by hak8or. Example toml file; ``` gitea_url = "https://gitmirror.hak8or.com" api_key = "api_key_goes_here" repos = [ { url = "https://gitea.hak8or.com/hak8or/gitea_mirror.git" }, { rename = "cool_rename", url = "https://gitea.hak8or.com/hak8or/gitea_mirror.git" }, { rename = "cool_another_rename", url = "https://gitea.hak8or.com/hak8or/gitea_mirror.git" }, { rename = "rusty_rust", url = "https://github.com/rust-lang/rust.git" }, ] ``` Ensure the script is as minimal as possible, do not use libraries if you can avoid them (except clap for CLI arguments, tracing for logging, actix for async and web interactions, reqwest for actual queries, and serde_json for json, or whatever else is commonly used in rust). I will be invoking this tool with a systemd timer. ```EOF
This commit is contained in:
470
Cargo.lock
generated
470
Cargo.lock
generated
@@ -67,18 +67,6 @@ dependencies = [
|
|||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anyhow"
|
|
||||||
version = "1.0.100"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomic-waker"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@@ -102,9 +90,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.21.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
@@ -319,17 +313,6 @@ dependencies = [
|
|||||||
"pin-utils",
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -352,7 +335,6 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
|||||||
name = "gitea_mirror"
|
name = "gitea_mirror"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"clap",
|
"clap",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -361,20 +343,19 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.12"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
|
checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"slab",
|
"slab",
|
||||||
@@ -397,9 +378,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "1.3.1"
|
version = "0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
|
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"fnv",
|
"fnv",
|
||||||
@@ -408,24 +389,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http-body"
|
name = "http-body"
|
||||||
version = "1.0.1"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
|
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"http",
|
"http",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "http-body-util"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-core",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -435,84 +404,47 @@ version = "1.10.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpdate"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.7.0"
|
version = "0.14.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
|
checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
|
||||||
"bytes",
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"h2",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"httparse",
|
|
||||||
"itoa",
|
|
||||||
"pin-project-lite",
|
|
||||||
"pin-utils",
|
|
||||||
"smallvec",
|
|
||||||
"tokio",
|
|
||||||
"want",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-rustls"
|
|
||||||
version = "0.27.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
|
|
||||||
dependencies = [
|
|
||||||
"http",
|
|
||||||
"hyper",
|
|
||||||
"hyper-util",
|
|
||||||
"rustls",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"tokio",
|
|
||||||
"tokio-rustls",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-tls"
|
|
||||||
version = "0.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"http-body-util",
|
|
||||||
"hyper",
|
|
||||||
"hyper-util",
|
|
||||||
"native-tls",
|
|
||||||
"tokio",
|
|
||||||
"tokio-native-tls",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-util"
|
|
||||||
version = "0.1.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
|
|
||||||
dependencies = [
|
|
||||||
"base64",
|
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"hyper",
|
"httparse",
|
||||||
"ipnet",
|
"httpdate",
|
||||||
"libc",
|
"itoa",
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2 0.5.10",
|
||||||
"system-configuration",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-registry",
|
"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]]
|
[[package]]
|
||||||
@@ -638,7 +570,7 @@ version = "0.7.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -649,16 +581,6 @@ version = "2.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iri-string"
|
|
||||||
version = "0.7.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@@ -806,7 +728,7 @@ version = "0.10.73"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -930,61 +852,47 @@ version = "0.5.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.23"
|
version = "0.11.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
|
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
"h2",
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"http-body-util",
|
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
|
||||||
"hyper-tls",
|
"hyper-tls",
|
||||||
"hyper-util",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls-pki-types",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tower",
|
|
||||||
"tower-http",
|
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"url",
|
"url",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
"winreg",
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ring"
|
|
||||||
version = "0.17.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"cfg-if",
|
|
||||||
"getrandom 0.2.16",
|
|
||||||
"libc",
|
|
||||||
"untrusted",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -999,7 +907,7 @@ version = "1.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
@@ -1007,36 +915,12 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls-pemfile"
|
||||||
version = "0.23.32"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40"
|
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"base64",
|
||||||
"rustls-pki-types",
|
|
||||||
"rustls-webpki",
|
|
||||||
"subtle",
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-pki-types"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
|
|
||||||
dependencies = [
|
|
||||||
"zeroize",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustls-webpki"
|
|
||||||
version = "0.103.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb"
|
|
||||||
dependencies = [
|
|
||||||
"ring",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"untrusted",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1072,7 +956,7 @@ version = "2.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.9.4",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1134,11 +1018,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "1.0.2"
|
version = "0.6.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
|
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1189,6 +1073,16 @@ version = "1.15.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -1211,12 +1105,6 @@ version = "0.11.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subtle"
|
|
||||||
version = "2.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.106"
|
version = "2.0.106"
|
||||||
@@ -1230,12 +1118,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sync_wrapper"
|
name = "sync_wrapper"
|
||||||
version = "1.0.2"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "synstructure"
|
||||||
@@ -1250,20 +1135,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"system-configuration-sys",
|
"system-configuration-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration-sys"
|
name = "system-configuration-sys"
|
||||||
version = "0.6.0"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
|
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1276,7 +1161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53"
|
checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.3.3",
|
"getrandom",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.61.0",
|
"windows-sys 0.61.0",
|
||||||
@@ -1316,7 +1201,7 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"slab",
|
"slab",
|
||||||
"socket2",
|
"socket2 0.6.0",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
@@ -1342,16 +1227,6 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-rustls"
|
|
||||||
version = "0.26.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd"
|
|
||||||
dependencies = [
|
|
||||||
"rustls",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.16"
|
version = "0.7.16"
|
||||||
@@ -1367,81 +1242,44 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.9.7"
|
version = "0.8.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
|
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"serde",
|
||||||
"serde_core",
|
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"toml_parser",
|
"toml_edit",
|
||||||
"toml_writer",
|
|
||||||
"winnow",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.7.2"
|
version = "0.6.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
|
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_parser"
|
name = "toml_edit"
|
||||||
version = "1.0.3"
|
version = "0.22.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
|
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_write",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_writer"
|
name = "toml_write"
|
||||||
version = "1.0.3"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
|
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"pin-project-lite",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tokio",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-http"
|
|
||||||
version = "0.6.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"bytes",
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"iri-string",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tower",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower-layer"
|
|
||||||
version = "0.3.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
@@ -1518,12 +1356,6 @@ version = "1.0.19"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "untrusted"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.5.7"
|
version = "2.5.7"
|
||||||
@@ -1688,32 +1520,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-registry"
|
name = "windows-sys"
|
||||||
version = "0.5.3"
|
version = "0.48.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link 0.1.3",
|
"windows-targets 0.48.5",
|
||||||
"windows-result",
|
|
||||||
"windows-strings",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-result"
|
|
||||||
version = "0.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
|
||||||
dependencies = [
|
|
||||||
"windows-link 0.1.3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-strings"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
|
||||||
dependencies = [
|
|
||||||
"windows-link 0.1.3",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1752,6 +1564,21 @@ dependencies = [
|
|||||||
"windows-link 0.2.0",
|
"windows-link 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1785,6 +1612,12 @@ dependencies = [
|
|||||||
"windows_x86_64_msvc 0.53.0",
|
"windows_x86_64_msvc 0.53.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1797,6 +1630,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1809,6 +1648,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1833,6 +1678,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1845,6 +1696,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1857,6 +1714,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1869,6 +1732,12 @@ version = "0.53.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@@ -1886,6 +1755,19 @@ name = "winnow"
|
|||||||
version = "0.7.13"
|
version = "0.7.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.50.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
@@ -1944,12 +1826,6 @@ dependencies = [
|
|||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zeroize"
|
|
||||||
version = "1.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerotrie"
|
name = "zerotrie"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
10
Cargo.toml
10
Cargo.toml
@@ -4,13 +4,11 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.100"
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
clap = { version = "4.5", features = ["derive", "env"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
reqwest = { version = "0.12.23", features = ["json"] }
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tokio = { version = "1.35", features = ["full"] }
|
toml = "0.8"
|
||||||
toml = "0.9.7"
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = "0.3"
|
tracing-subscriber = "0.3"
|
||||||
url = "2.5.7"
|
|
||||||
|
441
src/main.rs
441
src/main.rs
@@ -1,229 +1,326 @@
|
|||||||
use anyhow::{Context, Result};
|
//! # Gitea Mirror
|
||||||
use clap::Parser;
|
//!
|
||||||
use reqwest::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT};
|
//! A simple command-line tool to ensure a list of remote git repositories are mirrored to a Gitea instance.
|
||||||
use serde::{Deserialize, Serialize};
|
//! It checks if a repository already exists and, if not, creates a mirror migration.
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use tracing::{error, info, warn};
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
// --- Structs (Unchanged) ---
|
use clap::Parser;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use tracing::{Level, error, info, instrument, warn};
|
||||||
|
use tracing_subscriber;
|
||||||
|
|
||||||
|
// Represents the command-line arguments.
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(
|
#[clap(author, version, about, long_about = None)]
|
||||||
author,
|
struct Args {
|
||||||
version,
|
/// Path to the TOML configuration file.
|
||||||
about = "A simple tool to ensure git repositories are mirrored to Gitea."
|
#[clap(short, long, value_parser)]
|
||||||
)]
|
|
||||||
struct Cli {
|
|
||||||
#[arg(short, long, env = "GITEA_MIRROR_CONFIG")]
|
|
||||||
config: PathBuf,
|
config: PathBuf,
|
||||||
#[arg(long)]
|
|
||||||
|
/// Perform a dry run without creating any migrations.
|
||||||
|
#[clap(short, long)]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
// Represents a single repository entry in the config file.
|
||||||
struct RepoToMirror {
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
struct RepoConfig {
|
||||||
url: String,
|
url: String,
|
||||||
rename: Option<String>,
|
rename: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents the main structure of the TOML configuration file.
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct Config {
|
struct Config {
|
||||||
gitea_url: String,
|
gitea_url: String,
|
||||||
api_key: String,
|
api_key: String,
|
||||||
repos: Vec<RepoToMirror>,
|
repos: Option<Vec<RepoConfig>>,
|
||||||
|
organizations: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Gitea API Structs (Corrected) ---
|
// Represents the payload for creating a migration in Gitea.
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(serde::Serialize, Debug)]
|
||||||
struct GiteaUser {
|
struct MigrateRepoPayload<'a> {
|
||||||
id: i64,
|
|
||||||
login: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
// **MODIFIED**: This struct now includes `name` and the correct `mirror_url` field.
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
struct GiteaRepo {
|
|
||||||
name: String,
|
|
||||||
mirror: bool,
|
|
||||||
mirror_url: Option<String>, // The original source URL of the mirror
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
|
||||||
struct MigrationRequest<'a> {
|
|
||||||
clone_addr: &'a str,
|
clone_addr: &'a str,
|
||||||
uid: i64,
|
|
||||||
repo_name: &'a str,
|
repo_name: &'a str,
|
||||||
mirror: bool,
|
mirror: bool,
|
||||||
private: bool,
|
private: bool,
|
||||||
description: String,
|
description: &'a str,
|
||||||
|
uid: i64, // The user ID of the owner. We'll fetch this.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Represents a user as returned by the Gitea API.
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct GiteaUser {
|
||||||
|
id: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Entry point of the application.
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tracing_subscriber::fmt::init();
|
// Initialize the tracing subscriber for logging.
|
||||||
let cli = Cli::parse();
|
tracing_subscriber::fmt().with_max_level(Level::INFO).init();
|
||||||
|
|
||||||
let config_content = fs::read_to_string(&cli.config)
|
// Parse command-line arguments or get config path from environment variable.
|
||||||
.with_context(|| format!("Failed to read config file at {:?}", cli.config))?;
|
let args = match Args::try_parse() {
|
||||||
let config: Config =
|
Ok(args) => args,
|
||||||
toml::from_str(&config_content).context("Failed to parse TOML configuration")?;
|
Err(_) => {
|
||||||
|
// If parsing fails, check for the environment variable.
|
||||||
|
if let Ok(config_path) = env::var("GITEA_MIRROR_CONFIG") {
|
||||||
|
Args {
|
||||||
|
config: PathBuf::from(config_path),
|
||||||
|
// Check for a dry-run env var as well, defaulting to false.
|
||||||
|
dry_run: env::var("GITEA_MIRROR_DRY_RUN")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse()
|
||||||
|
.unwrap_or(false),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If no env var, show help and exit.
|
||||||
|
Args::parse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if cli.dry_run {
|
info!("Starting Gitea mirror process. Dry run: {}", args.dry_run);
|
||||||
info!("Performing a dry run. No migrations will be created.");
|
|
||||||
|
// Read and parse the configuration file.
|
||||||
|
let config = load_config(&args.config)?;
|
||||||
|
let http_client = reqwest::Client::new();
|
||||||
|
|
||||||
|
// Fetch the Gitea user ID for the authenticated user.
|
||||||
|
let user_id = get_gitea_user_id(&http_client, &config.gitea_url, &config.api_key).await?;
|
||||||
|
info!(
|
||||||
|
"Successfully authenticated and retrieved user ID: {}",
|
||||||
|
user_id
|
||||||
|
);
|
||||||
|
|
||||||
|
// Process repositories from the static list.
|
||||||
|
if let Some(repos) = &config.repos {
|
||||||
|
for repo_config in repos {
|
||||||
|
process_repo(
|
||||||
|
&repo_config.url,
|
||||||
|
repo_config.rename.as_deref(),
|
||||||
|
user_id,
|
||||||
|
&http_client,
|
||||||
|
&config,
|
||||||
|
args.dry_run,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut headers = reqwest::header::HeaderMap::new();
|
// Process repositories from the organizations/users list.
|
||||||
headers.insert(ACCEPT, "application/json".parse()?);
|
if let Some(org_urls) = &config.organizations {
|
||||||
headers.insert(CONTENT_TYPE, "application/json".parse()?);
|
for org_url in org_urls {
|
||||||
headers.insert(USER_AGENT, "gitea-mirror-tool/0.1.0".parse()?);
|
info!("Fetching repositories from organization: {}", org_url);
|
||||||
headers.insert(AUTHORIZATION, format!("token {}", config.api_key).parse()?);
|
match fetch_org_repos(&http_client, org_url, &config.api_key).await {
|
||||||
let client = reqwest::Client::builder()
|
Ok(repo_urls) => {
|
||||||
.default_headers(headers)
|
info!("Found {} repositories for {}", repo_urls.len(), org_url);
|
||||||
.build()?;
|
for url in repo_urls {
|
||||||
|
process_repo(
|
||||||
|
&url,
|
||||||
|
None, // No rename support for orgs
|
||||||
|
user_id,
|
||||||
|
&http_client,
|
||||||
|
&config,
|
||||||
|
args.dry_run,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => error!("Failed to fetch repos from {}: {}", org_url, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
info!("🔗 Connecting to Gitea instance at {}", config.gitea_url);
|
info!("Gitea mirror process completed.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
let user_url = format!("{}/api/v1/user", config.gitea_url);
|
/// Loads and parses the TOML configuration file.
|
||||||
let user = client
|
#[instrument(skip(path))]
|
||||||
.get(&user_url)
|
fn load_config(path: &Path) -> Result<Config, Box<dyn std::error::Error>> {
|
||||||
|
info!("Loading configuration from: {:?}", path);
|
||||||
|
let content = fs::read_to_string(path)?;
|
||||||
|
let config: Config = toml::from_str(&content)?;
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetches the authenticated user's ID from Gitea.
|
||||||
|
#[instrument(skip(http_client, gitea_url, api_key))]
|
||||||
|
async fn get_gitea_user_id(
|
||||||
|
http_client: &reqwest::Client,
|
||||||
|
gitea_url: &str,
|
||||||
|
api_key: &str,
|
||||||
|
) -> Result<i64, reqwest::Error> {
|
||||||
|
let url = format!("{}/api/v1/user", gitea_url);
|
||||||
|
let user: GiteaUser = http_client
|
||||||
|
.get(&url)
|
||||||
|
.header("Authorization", format!("token {}", api_key))
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
.json::<GiteaUser>()
|
.json()
|
||||||
.await
|
.await?;
|
||||||
.context("Failed to get Gitea user info. Check your API key and Gitea URL.")?;
|
Ok(user.id)
|
||||||
info!("Authenticated as user '{}' (ID: {})", user.login, user.id);
|
}
|
||||||
|
|
||||||
// **MODIFIED**: We now build two sets: one for source URLs and one for existing repo names.
|
/// Checks if a repository already exists in Gitea for the user.
|
||||||
info!("🔍 Fetching all existing repositories to build a local cache...");
|
#[instrument(skip(http_client, gitea_url, api_key))]
|
||||||
let mut existing_mirror_sources: HashSet<String> = HashSet::new();
|
async fn repo_exists(
|
||||||
let mut existing_repo_names: HashSet<String> = HashSet::new();
|
http_client: &reqwest::Client,
|
||||||
|
gitea_url: &str,
|
||||||
|
api_key: &str,
|
||||||
|
repo_name: &str,
|
||||||
|
) -> Result<bool, reqwest::Error> {
|
||||||
|
let url = format!("{}/api/v1/repos/search", gitea_url);
|
||||||
|
let response: serde_json::Value = http_client
|
||||||
|
.get(&url)
|
||||||
|
.query(&[("q", repo_name), ("limit", "1")])
|
||||||
|
.header("Authorization", format!("token {}", api_key))
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some(data) = response.get("data").and_then(|d| d.as_array()) {
|
||||||
|
for repo in data {
|
||||||
|
if let Some(name) = repo.get("name").and_then(|n| n.as_str()) {
|
||||||
|
if name.eq_ignore_ascii_case(repo_name) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a mirror migration in Gitea.
|
||||||
|
#[instrument(skip(http_client, config, payload))]
|
||||||
|
async fn create_migration(
|
||||||
|
http_client: &reqwest::Client,
|
||||||
|
config: &Config,
|
||||||
|
payload: &MigrateRepoPayload<'_>,
|
||||||
|
) -> Result<(), reqwest::Error> {
|
||||||
|
let url = format!("{}/api/v1/repos/migrate", config.gitea_url);
|
||||||
|
http_client
|
||||||
|
.post(&url)
|
||||||
|
.header("Authorization", format!("token {}", config.api_key))
|
||||||
|
.json(payload)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetches all repository clone URLs from a given Gitea/GitHub organization/user page.
|
||||||
|
#[instrument(skip(http_client, api_key))]
|
||||||
|
async fn fetch_org_repos(
|
||||||
|
http_client: &reqwest::Client,
|
||||||
|
org_url: &str,
|
||||||
|
api_key: &str,
|
||||||
|
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
||||||
|
// This is a simplified fetcher. It assumes Gitea API compatibility.
|
||||||
|
// For GitHub, you might need a different base URL and auth method.
|
||||||
|
let api_url = if org_url.contains("github.com") {
|
||||||
|
let parts: Vec<&str> = org_url.trim_end_matches('/').split('/').collect();
|
||||||
|
let user_or_org = parts.last().ok_or("Invalid GitHub URL")?;
|
||||||
|
format!("https://api.github.com/users/{}/repos", user_or_org)
|
||||||
|
} else {
|
||||||
|
// Assuming Gitea-like URL structure
|
||||||
|
let parts: Vec<&str> = org_url.trim_end_matches('/').split('/').collect();
|
||||||
|
let user_or_org = parts.last().ok_or("Invalid Gitea URL")?;
|
||||||
|
format!(
|
||||||
|
"{}s/{}/repos",
|
||||||
|
org_url.replace(user_or_org, &format!("api/v1/user")),
|
||||||
|
user_or_org
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
info!("Querying API endpoint: {}", api_url);
|
||||||
|
|
||||||
|
let mut repos: Vec<String> = Vec::new();
|
||||||
let mut page = 1;
|
let mut page = 1;
|
||||||
loop {
|
loop {
|
||||||
let repos_url = format!("{}/api/v1/user/repos", config.gitea_url);
|
let response: Vec<serde_json::Value> = http_client
|
||||||
let repos_on_page = client
|
.get(&api_url)
|
||||||
.get(&repos_url)
|
.query(&[("page", page.to_string())])
|
||||||
.query(&[("limit", "50"), ("page", &page.to_string())])
|
// For GitHub, a User-Agent is required.
|
||||||
|
.header("User-Agent", "gitea-mirror-rust-client")
|
||||||
|
.header("Authorization", format!("token {}", api_key))
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
.json::<Vec<GiteaRepo>>()
|
.json()
|
||||||
.await
|
.await?;
|
||||||
.context("Failed to fetch a page of existing repositories.")?;
|
|
||||||
|
|
||||||
if repos_on_page.is_empty() {
|
if response.is_empty() {
|
||||||
break;
|
break; // No more pages
|
||||||
}
|
}
|
||||||
|
|
||||||
for repo in repos_on_page {
|
for repo in response {
|
||||||
// Add the name of EVERY repo to prevent any name collisions.
|
if let Some(clone_url) = repo.get("clone_url").and_then(|u| u.as_str()) {
|
||||||
existing_repo_names.insert(repo.name);
|
repos.push(clone_url.to_string());
|
||||||
|
|
||||||
// If it's a mirror, store its ORIGINAL source URL for an exact match.
|
|
||||||
if repo.mirror {
|
|
||||||
if let Some(mirror_url) = repo.mirror_url {
|
|
||||||
existing_mirror_sources.insert(mirror_url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page += 1;
|
page += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!(
|
Ok(repos)
|
||||||
"Found {} existing repositories and {} configured mirrors.",
|
}
|
||||||
existing_repo_names.len(),
|
|
||||||
existing_mirror_sources.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
// **MODIFIED**: The main checking logic is now much more robust.
|
/// Core logic to process a single repository.
|
||||||
for repo_config in &config.repos {
|
#[instrument(skip(user_id, http_client, config, dry_run))]
|
||||||
let url_to_mirror = &repo_config.url;
|
async fn process_repo(
|
||||||
|
repo_url: &str,
|
||||||
|
rename: Option<&str>,
|
||||||
|
user_id: i64,
|
||||||
|
http_client: &reqwest::Client,
|
||||||
|
config: &Config,
|
||||||
|
dry_run: bool,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let repo_name = match rename {
|
||||||
|
Some(name) => name,
|
||||||
|
None => extract_repo_name(repo_url).ok_or("Could not extract repo name from URL")?,
|
||||||
|
};
|
||||||
|
|
||||||
// CHECK 1: Has this exact source URL already been mirrored?
|
info!("Processing repo '{}' -> '{}'", repo_url, repo_name);
|
||||||
if existing_mirror_sources.contains(url_to_mirror) {
|
|
||||||
info!(
|
|
||||||
"Mirror for source URL '{}' already exists. Skipping.",
|
|
||||||
url_to_mirror
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the target name for the new repository.
|
if repo_exists(http_client, &config.gitea_url, &config.api_key, repo_name).await? {
|
||||||
let target_repo_name = match &repo_config.rename {
|
info!("Repo '{}' already exists. Skipping.", repo_name);
|
||||||
Some(name) => name.clone(),
|
} else {
|
||||||
None => get_repo_name_from_url(url_to_mirror).with_context(|| {
|
warn!("Repo '{}' does not exist. Migration needed.", repo_name);
|
||||||
format!("Could not parse repo name from URL: {}", url_to_mirror)
|
if !dry_run {
|
||||||
})?,
|
info!("Initiating migration for '{}'...", repo_name);
|
||||||
};
|
let payload = MigrateRepoPayload {
|
||||||
|
clone_addr: repo_url,
|
||||||
// CHECK 2: Will creating this mirror cause a name collision?
|
repo_name,
|
||||||
if existing_repo_names.contains(&target_repo_name) {
|
mirror: true,
|
||||||
warn!(
|
private: false, // Defaulting to public, change if needed
|
||||||
"Cannot create mirror for '{}'. A repository named '{}' already exists. Skipping.",
|
description: "",
|
||||||
url_to_mirror, target_repo_name
|
uid: user_id,
|
||||||
);
|
};
|
||||||
continue;
|
if let Err(e) = create_migration(http_client, config, &payload).await {
|
||||||
}
|
error!("Failed to create migration for '{}': {}", repo_name, e);
|
||||||
|
} else {
|
||||||
// If both checks pass, we are clear to create the migration.
|
info!("Successfully started migration for '{}'.", repo_name);
|
||||||
info!(
|
}
|
||||||
"Mirror for '{}' not found and name '{}' is available. Needs creation.",
|
|
||||||
url_to_mirror, target_repo_name
|
|
||||||
);
|
|
||||||
|
|
||||||
if cli.dry_run {
|
|
||||||
warn!(
|
|
||||||
"--dry-run enabled, skipping migration for '{}'.",
|
|
||||||
url_to_mirror
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let migration_payload = MigrationRequest {
|
|
||||||
clone_addr: url_to_mirror,
|
|
||||||
uid: user.id,
|
|
||||||
repo_name: &target_repo_name,
|
|
||||||
mirror: true,
|
|
||||||
private: false,
|
|
||||||
description: format!("Mirror of {}", url_to_mirror),
|
|
||||||
};
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"🚀 Creating migration for '{}' as new repo '{}'...",
|
|
||||||
url_to_mirror, target_repo_name
|
|
||||||
);
|
|
||||||
|
|
||||||
let migrate_url = format!("{}/api/v1/repos/migrate", config.gitea_url);
|
|
||||||
let response = client
|
|
||||||
.post(&migrate_url)
|
|
||||||
.json(&migration_payload)
|
|
||||||
.send()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
if response.status().is_success() {
|
|
||||||
info!("Successfully initiated migration for '{}'.", url_to_mirror);
|
|
||||||
} else {
|
} else {
|
||||||
let status = response.status();
|
info!(
|
||||||
let error_body = response
|
"Dry run enabled. Skipping actual migration for '{}'.",
|
||||||
.text()
|
repo_name
|
||||||
.await
|
|
||||||
.unwrap_or_else(|_| "Could not read error body".to_string());
|
|
||||||
error!(
|
|
||||||
"Failed to create migration for '{}'. Status: {}. Body: {}",
|
|
||||||
url_to_mirror, status, error_body
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("All tasks completed.");
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_repo_name_from_url(git_url: &str) -> Option<String> {
|
/// Extracts a repository name from a git URL (e.g., "https://.../repo.git" -> "repo").
|
||||||
Url::parse(git_url)
|
fn extract_repo_name(url: &str) -> Option<&str> {
|
||||||
.ok()
|
url.split('/').last().map(|s| s.trim_end_matches(".git"))
|
||||||
.and_then(|url| url.path_segments()?.last().map(|s| s.to_string()))
|
|
||||||
.map(|name| name.strip_suffix(".git").unwrap_or(&name).to_string())
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user