diff --git a/CHANGELOG.md b/CHANGELOG.md index c12548c..dbf9eee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.0] - 2020-10-05 + +### Added + +- add support for remote url without `.git` extension + +### Changed + +- complete refactor of the code +- remove custom code for BROWSER environment variable + ## [0.1.13] - 2020-06-20 ### Added diff --git a/Cargo.lock b/Cargo.lock index ba4f531..27f515b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,474 +2,566 @@ # It is not intended for manual editing. [[package]] name = "aho-corasick" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b" + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi", ] [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "cc" -version = "1.0.54" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" dependencies = [ - "jobserver 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver", ] [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] [[package]] name = "clap" -version = "2.33.1" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "flexi_logger" +version = "0.15.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaab3caedb4149800f91e8e4899f29cd9ddf3b569b04c365ca9334f92f7542bf" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "chrono", + "glob", + "lazy_static", + "log", + "regex", + "thiserror", + "yansi", ] [[package]] name = "git2" -version = "0.13.10" +version = "0.13.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e094214efbc7fdbbdee952147e493b00e99a4e52817492277e98967ae918165" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "libgit2-sys 0.12.12+1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", ] [[package]] name = "gitweb" -version = "0.1.13" +version = "0.2.0" dependencies = [ - "git2 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)", - "open 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "flexi_logger", + "git2", + "log", + "open", + "regex", + "structopt", + "thiserror", ] +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" dependencies = [ - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "jobserver" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" dependencies = [ - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa7087f49d294270db4e1928fc110c976cd4b9e5a16348e0a1df09afa99e6c98" [[package]] name = "libgit2-sys" -version = "0.12.12+1.0.1" +version = "0.12.13+1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069eea34f76ec15f2822ccf78fe0cdb8c9016764d0a12865278585a74dbdeae5" dependencies = [ - "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "libssh2-sys 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", ] [[package]] name = "libssh2-sys" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" dependencies = [ - "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "libz-sys 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", ] [[package]] name = "libz-sys" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" dependencies = [ - "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "memchr" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "num-integer" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +dependencies = [ + "autocfg", +] [[package]] name = "open" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi", ] [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" version = "0.9.58" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pkg-config" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" [[package]] name = "proc-macro-error" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", ] [[package]] name = "proc-macro-error-attr" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "regex" version = "1.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" dependencies = [ - "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-syntax" version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33f6461027d7f08a13715659b2948e1602c31a3756aeae9378bfe7518c72e82" dependencies = [ - "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92e775028122a4b3dd55d58f14fc5120289c69bee99df1d117ae30f84b225c9" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "syn" -version = "1.0.32" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c51d92969d209b54a98397e1b91c8ae82d8c87a7bb87df0b29aa2ad81454228" dependencies = [ - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "syn-mid" -version = "0.5.0" +name = "textwrap" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "thiserror" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" dependencies = [ - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", ] [[package]] name = "tinyvec" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" dependencies = [ - "tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tinyvec", ] [[package]] name = "unicode-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "idna", + "matches", + "percent-encoding", ] [[package]] name = "vcpkg" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" [[package]] name = "vec_map" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[metadata] -"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum cc 1.0.54 (registry+https://github.com/rust-lang/crates.io-index)" = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" -"checksum git2 0.13.10 (registry+https://github.com/rust-lang/crates.io-index)" = "86d97249f21e9542caeee9f8e1d150905cd875bf723f5ff771bdb4852eb83a24" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum jobserver 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" -"checksum libgit2-sys 0.12.12+1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0100ae90655025134424939f1f60e27e879460d451dff6afedde4f8226cbebfc" -"checksum libssh2-sys 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" -"checksum libz-sys 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af67924b8dd885cccea261866c8ce5b74d239d272e154053ff927dae839f5ae9" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" -"checksum open 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.58 (registry+https://github.com/rust-lang/crates.io-index)" = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" -"checksum proc-macro-error 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" -"checksum proc-macro-error-attr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" -"checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" -"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" -"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" -"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc388d94ffabf39b5ed5fadddc40147cb21e605f53db6f8f36a625d27489ac5" -"checksum structopt-derive 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2513111825077552a6751dfad9e11ce0fba07d7276a3943a037d7e93e64c5f" -"checksum syn 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "a994520748611c17d163e81b6c4a4b13d11b7f63884362ab2efac3aa9cf16d00" -"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -"checksum vcpkg 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" -"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" -"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "yansi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" diff --git a/Cargo.toml b/Cargo.toml index aef7055..1cdc7cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gitweb" -version = "0.1.13" +version = "0.2.0" authors = ["Yoann Fleury "] edition = "2018" description = "Open the current remote repository in your browser" @@ -22,3 +22,7 @@ regex = "1" structopt = "0.3" open = "1.4" git2 = "0.13" +log = "0.4" +flexi_logger = "0.15" +anyhow = "1.0" +thiserror = "1.0" diff --git a/src/git.rs b/src/git.rs index 78032d6..1d3a88f 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,30 +1,35 @@ -use crate::logger::Logger; -use git2::{Error, ErrorCode, Repository}; +use crate::Issue; +use anyhow::Result; +use git2::{ErrorCode, Repository}; /// Get the current repository. -pub fn get_repo() -> Result { +// Will check that the user is in a git repository. +pub fn get_repo() -> Result { const CURRENT_WORKING_DIRECTORY: &str = "."; - Repository::discover(CURRENT_WORKING_DIRECTORY) + let repo = + Repository::discover(CURRENT_WORKING_DIRECTORY).map_err(|_| Issue::NotInAGitRepository)?; + + Ok(repo) } // Get the current branch or return master. -pub fn get_branch(repo: &Repository, logger: &Logger) -> String { +pub fn get_branch(repo: &Repository) -> String { let head = match repo.head() { Ok(head) => Some(head), Err(ref e) if e.code() == ErrorCode::UnbornBranch || e.code() == ErrorCode::NotFound => { None } - Err(e) => panic!("failed to get head ref {}", e), + Err(e) => { + error!("failed to get head ref '{}'", e); + None + } }; let head = head.as_ref().and_then(|h| h.shorthand()); - logger.verbose_print( - format!( - "# On branch {}", - head.unwrap_or("Not currently on any branch") - ) - .as_str(), + debug!( + "On branch '{}'", + head.unwrap_or("Not currently on any branch") ); String::from(head.unwrap_or("master")) diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1df6805 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,243 @@ +use regex::Regex; +use thiserror::Error; + +use crate::options::Opt; + +#[macro_use] +extern crate log; + +mod git; +pub mod options; + +#[derive(Debug, Eq, Error, PartialEq, Clone)] +pub enum Issue { + #[error("Command failed, please run command inside a git directory")] + NotInAGitRepository, + #[error("No matching remote url found for '{0}' remote name")] + NoRemoteMatching(String), + #[error("No remote available")] + NoRemoteAvailable, + #[error("Not able to open system browser")] + NotAbleToOpenSystemBrowser, + #[error("Unable to open browser '{0}'")] + BrowserNotAvailable(String), + #[error("Unable to get remote parts, please open an issue as it might come from the code")] + UnableToGetRemoteParts, +} + +pub struct Success; +type Result = core::result::Result; + +impl Issue { + pub fn exit_code(&self) -> i32 { + match self { + Self::NotInAGitRepository => 1, + Self::NoRemoteMatching(..) => 2, + Self::NoRemoteAvailable => 3, + Self::NotAbleToOpenSystemBrowser => 4, + Self::BrowserNotAvailable(..) => 5, + Self::UnableToGetRemoteParts => 6, + } + } +} + +enum GitProvider { + GitHub, + GitLab, + Bitbucket, + Gitea, +} + +impl Default for GitProvider { + fn default() -> Self { + Self::GitHub + } +} + +impl GitProvider { + fn hostname(&self) -> String { + match self { + Self::GitHub => "github.com", + Self::GitLab => "gitlab.com", + Self::Bitbucket => "bitbucket.org", + Self::Gitea => "gitea.io", + } + .to_string() + } +} + +pub struct RemoteParts { + domain: String, + repository: String, +} + +const DEFAULT_REMOTE_ORIGIN: &str = "origin"; + +pub fn get_remote_parts(url: &str) -> anyhow::Result { + let re: Regex = Regex::new(r"((\w+://)|(git@))(.+@)*(?P[\w\d.]+)(:[\d]+)?/*(:?)(?P[^.]*)(\.git)?(/)?$").unwrap(); + + let caps = re + .captures(url) + .ok_or_else(|| ()) + .map_err(|_| Issue::UnableToGetRemoteParts)?; + + let domain = caps + .name("domain") + .map_or(GitProvider::GitHub.hostname(), |m| m.as_str().to_string()); + let repository = caps + .name("repository") + .map_or("".to_string(), |m| m.as_str().to_string()); + + Ok(RemoteParts { domain, repository }) +} + +pub fn run(opt: Opt) -> Result { + // let logger = logger::Logger::new(opt.verbose); + debug!("Verbose mode is active"); + + let repo = git::get_repo()?; + + // Get the tag to show in the browser. If the option is given, then the value + // will be used as it is an alias for branch. + let reference = if let Some(tag) = opt.tag { + tag + } else { + // Get the branch to show in the browser. If the option is given, then, the + // value will be used, else, the current branch is given, or master if + // something went wrong. + opt.branch.unwrap_or_else(|| { + debug!("No branch given, getting current one"); + git::get_branch(&repo) + }) + }; + + let remote_name = &opt + .remote + .unwrap_or_else(|| String::from(DEFAULT_REMOTE_ORIGIN)); + + debug!("Getting remote url for '{}' remote name", remote_name); + + let optional_remote = repo + .find_remote(remote_name) + .map_err(|_| Issue::NoRemoteMatching(remote_name.clone()))?; + + let remote_url = optional_remote + .url() + .ok_or_else(|| ()) + .map_err(|_| Issue::NoRemoteAvailable)?; + + let RemoteParts { domain, repository } = get_remote_parts(remote_url).unwrap(); + + let (path, tail) = if let Some(commit) = opt.commit { + let path = if domain == GitProvider::Bitbucket.hostname() { + "commits" + } else { + "commit" + }; + + (path, commit) + } else { + let path = if domain == GitProvider::Bitbucket.hostname() { + "src" + } else { + "tree" + }; + + (path, reference) + }; + + let url = format!( + "https://{domain}/{repository}/{path}/{tail}", + domain = domain, + path = path, + repository = repository, + tail = tail + ); + + // If the option is available through the command line, open the given one + match opt.browser { + Some(option_browser) => { + debug!("Browser '{}' given as option", option_browser); + + if option_browser == "" { + println!("{}", url); + } + + open::with(&url, &option_browser) + .map_err(|_| Issue::BrowserNotAvailable(option_browser))?; + + Ok(Success) + } + None => { + // Open the default web browser on the current system. + match open::that(&url) { + Ok(_) => { + debug!("Default browser is now open"); + Ok(Success) + } + Err(_) => Err(Issue::NotAbleToOpenSystemBrowser), + } + } + } +} + +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use super::*; + + #[test] + fn test_without_ssh_git_and_without_extension_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("git@github.com:yoannfleurydev/gitweb").unwrap(); + + assert_eq!(domain, "github.com"); + assert_eq!(repository, "yoannfleurydev/gitweb"); + } + + #[test] + fn test_without_ssh_git_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("git@github.com:yoannfleurydev/gitweb.git").unwrap(); + + assert_eq!(domain, "github.com"); + assert_eq!(repository, "yoannfleurydev/gitweb"); + } + + #[test] + fn test_with_ssh_and_multiple_subgroups_git_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("ssh://git@gitlab.com/group/subgroup/subsubgroup/design-system.git") + .unwrap(); + + assert_eq!(domain, "gitlab.com"); + assert_eq!(repository, "group/subgroup/subsubgroup/design-system"); + } + + #[test] + fn test_with_ssh_and_port_git_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("ssh://user@host.xz:22/path/to/repo.git/").unwrap(); + + assert_eq!(domain, "host.xz"); + assert_eq!(repository, "path/to/repo"); + } + + #[test] + fn test_with_http_and_port_git_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("http://host.xz:80/path/to/repo.git/").unwrap(); + + assert_eq!(domain, "host.xz"); + assert_eq!(repository, "path/to/repo"); + } + + #[test] + fn test_with_http_git_url_parts() { + let RemoteParts { domain, repository } = + get_remote_parts("https://host.xz/path/to/repo.git/").unwrap(); + + assert_eq!(domain, "host.xz"); + assert_eq!(repository, "path/to/repo"); + } +} diff --git a/src/logger.rs b/src/logger.rs deleted file mode 100644 index f295577..0000000 --- a/src/logger.rs +++ /dev/null @@ -1,19 +0,0 @@ -pub struct Logger { - verbose: bool, -} - -impl Logger { - pub fn new(verbose: bool) -> Logger { - Logger { verbose } - } - - pub fn verbose_print(&self, text: &str) { - if self.verbose { - println!("gitweb: {}", text); - } - } - - pub fn print(&self, text: &str) { - println!("{}", text); - } -} diff --git a/src/main.rs b/src/main.rs index 9f85ad4..a4f34fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,216 +1,25 @@ -extern crate git2; -extern crate open; -extern crate regex; -extern crate structopt; - -use regex::Regex; -use std::env; -use std::io::Result; +use flexi_logger::Logger; +use gitweb::options::Opt; +use gitweb::run; use std::process::exit; -use std::process::{Child, Command}; use structopt::StructOpt; -mod git; -mod logger; -mod options; - -/// Function to open the browser using the system shell. -fn open_browser(browser: &str, url: &str) -> Result { - Command::new(browser).arg(url).spawn() -} - -fn get_remote_parts(url: &str) -> Result<(&str, &str)> { - let re = - Regex::new(r"((\w+://)|(git@))(.+@)*([\w\d\.]+)(:[\d]+){0,1}/*(:?)(.*)\.git/?").unwrap(); - let caps = re.captures(url).unwrap(); - - let domain = caps.get(5).map_or("github.com", |m| m.as_str()); - let repository = caps.get(8).map_or("", |m| m.as_str()); - - Ok((domain, repository)) -} - -const BROWSER: &str = "BROWSER"; -const DEFAULT_REMOTE_ORIGIN: &str = "origin"; -const BITBUCKET_HOSTNAME: &str = "bitbucket.org"; - -/// Enumeration to store exit codes. The first one, Success is by default set to 0 -enum ExitCode { - Success, - NotInAGitRepository, - NoRemoteMatching, - NoRemoteAvailable, - NotAbleToOpenSystemBrowser, - BrowserNotAvailable, -} +#[macro_use] +extern crate log; fn main() { // Get the command line options - let opt = options::Opt::from_args(); - let logger = logger::Logger::new(opt.verbose); - logger.verbose_print("Verbose is active"); - - // Check that the user is in a git repository. - let repo = match git::get_repo() { - Ok(repo) => repo, - Err(_) => { - logger.print("Command failed, please run command inside a git directory"); - exit(ExitCode::NotInAGitRepository as i32); - } - }; + let opt = Opt::from_args(); - // Get the tag to show in the browser. If the option is given, then the value - // will be used as it is an alias for branch. - let reference = if let Some(tag) = opt.tag { tag } else { - // Get the branch to show in the browser. If the option is given, then, the - // value will be used, else, the current branch is given, or master if - // something went wrong. - match opt.branch { - Some(branch) => branch, - None => { - logger.verbose_print("No branch given, getting current one"); + Logger::with_str(if opt.verbose { "debug" } else { "info" }) + .start() + .unwrap_or_else(|e| panic!("Logger initialization failed with {}", e)); - git::get_branch(&repo, &logger) - } + match run(opt) { + Ok(_) => (), + Err(err) => { + info!("{}", err); + exit(err.exit_code()); } }; - - let remote_name = &opt - .remote - .unwrap_or_else(|| String::from(DEFAULT_REMOTE_ORIGIN)); - - logger.verbose_print(format!("Getting remote for {}", remote_name).as_str()); - - let optional_remote = match repo.find_remote(remote_name) { - Ok(remote) => remote, - Err(_) => { - logger.print(format!("No remote found for remote {}", remote_name).as_str()); - exit(ExitCode::NoRemoteMatching as i32); - } - }; - - let remote_url = match optional_remote.url() { - Some(remote) => remote, - None => { - logger.print("No remote URL available"); - exit(ExitCode::NoRemoteAvailable as i32); - } - }; - - let parts = get_remote_parts(remote_url).unwrap(); - - let url = if let Some(commit) = opt.commit { - format!( - "https://{domain}/{repository}/{path}/{commit}", - domain = parts.0, - path = if parts.0 == BITBUCKET_HOSTNAME {"commits"} else {"commit"}, - repository = parts.1, - commit = commit - ) - } else { - format!( - "https://{domain}/{repository}/{path}/{reference}", - domain = parts.0, - path = if parts.0 == BITBUCKET_HOSTNAME {"src"} else {"tree"}, - repository = parts.1, - reference = reference - ) - }; - - // If the option is available through the command line, open the given one - match opt.browser { - Some(option_browser) => { - logger.verbose_print(format!("Browser {} given as option", option_browser).as_str()); - - if option_browser == "" { - println!("{}", url); - exit(ExitCode::Success as i32); - } - - if open_browser(&option_browser, &url).is_err() { - logger.print( - format!("Unable to open the given browser: {}", option_browser).as_str(), - ); - exit(ExitCode::BrowserNotAvailable as i32); - }; - } - None => { - match env::var(BROWSER) { - // If the environment variable is available, open the web browser. - Ok(browser) => { - if open_browser(&browser, &url).is_err() { - logger.print( - format!("Unable to open the given browser: {}", browser).as_str(), - ); - exit(ExitCode::BrowserNotAvailable as i32); - } - } - // Else, open the default browser of the system. - Err(e) => { - logger.verbose_print( - format!("{} variable not available : {}", BROWSER, e).as_str(), - ); - - // Open the default web browser on the current system. - match open::that(&url) { - Ok(_) => logger.verbose_print("Default browser is now open"), - Err(_) => { - logger.print("Error while openning the default OS browser"); - exit(ExitCode::NotAbleToOpenSystemBrowser as i32); - } - } - } - } - } - } - - exit(ExitCode::Success as i32); -} - -#[cfg(test)] -mod tests { - // Note this useful idiom: importing names from outer (for mod tests) scope. - use super::*; - - #[test] - fn test_without_ssh_git_url_parts() { - let parts = get_remote_parts("git@github.com:yoannfleurydev/gitweb.git").unwrap(); - - assert_eq!(parts.0, "github.com"); - assert_eq!(parts.1, "yoannfleurydev/gitweb"); - } - - #[test] - fn test_with_ssh_and_multiple_subgroups_git_url_parts() { - let parts = - get_remote_parts("ssh://git@gitlab.com/group/subgroup/subsubgroup/design-system.git") - .unwrap(); - - assert_eq!(parts.0, "gitlab.com"); - assert_eq!(parts.1, "group/subgroup/subsubgroup/design-system"); - } - - #[test] - fn test_with_ssh_and_port_git_url_parts() { - let parts = get_remote_parts("ssh://user@host.xz:22/path/to/repo.git/").unwrap(); - - assert_eq!(parts.0, "host.xz"); - assert_eq!(parts.1, "path/to/repo"); - } - - #[test] - fn test_with_http_and_port_git_url_parts() { - let parts = get_remote_parts("http://host.xz:80/path/to/repo.git/").unwrap(); - - assert_eq!(parts.0, "host.xz"); - assert_eq!(parts.1, "path/to/repo"); - } - - #[test] - fn test_with_http_git_url_parts() { - let parts = get_remote_parts("https://host.xz/path/to/repo.git/").unwrap(); - - assert_eq!(parts.0, "host.xz"); - assert_eq!(parts.1, "path/to/repo"); - } } diff --git a/src/options.rs b/src/options.rs index c95ee8a..aae1443 100644 --- a/src/options.rs +++ b/src/options.rs @@ -38,7 +38,7 @@ pub struct Opt { /// web browser on the system /// If you give an empty string to browser option, the program will only /// print the remote URL into the stdout. - #[structopt(short = "-B", long)] + #[structopt(short = "-B", long, env)] pub browser: Option, /// Set the remote