Only command and commandfinish events are logged.
The dirty, logsource, track and ignore configuration items
are not supported yet.
To indicate commands executed without Python, a (rust) prefix is added
in corresponding log messages.
( )
| Alphare |
| hg-reviewers |
Only command and commandfinish events are logged.
The dirty, logsource, track and ignore configuration items
are not supported yet.
To indicate commands executed without Python, a (rust) prefix is added
in corresponding log messages.
| No Linters Available |
| No Unit Test Coverage |
| rust/rhg/src/blackbox.rs | ||
|---|---|---|
| 60 | Right. This comment was obsolete anyway so I’ve removed it. (date-format is part of this commit and there’s not quoting in config syntax outside of list-values, see previous commit.) | |
| 115 | Oh do you mean that (glob) expected output in .t files makes it hard to expect a literal ? character? https://docs.rs/users/0.11.0/users/fn.get_current_username.html says “This function to return None if the current user does not exist, which could happen if they were deleted after the program started running.” so I don’t expect this ??? fallback to show up a lot in practice and I think it’s not worth testing it. | |
| Path | Packages | |||
|---|---|---|---|---|
| M | rust/Cargo.lock (35 lines) | |||
| M | rust/hg-core/src/dirstate/parsers.rs (8 lines) | |||
| M | rust/hg-core/src/repo.rs (9 lines) | |||
| M | rust/hg-core/src/utils.rs (29 lines) | |||
| M | rust/rhg/Cargo.toml (2 lines) | |||
| A | M | rust/rhg/src/blackbox.rs (162 lines) | ||
| M | rust/rhg/src/main.rs (48 lines) | |||
| M | tests/test-rhg.t (12 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| d7ed1940b5f0 | 25379c31a1ea | Simon Sapin | Feb 16 2021, 7:08 AM |
| Status | Author | Revision | |
|---|---|---|---|
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin |
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| [[package]] | [[package]] | ||||
| name = "cfg-if" | name = "cfg-if" | ||||
| version = "1.0.0" | version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| [[package]] | [[package]] | ||||
| name = "chrono" | |||||
| version = "0.4.19" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||||
| dependencies = [ | |||||
| "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "num-integer 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| ] | |||||
| [[package]] | |||||
| name = "clap" | name = "clap" | ||||
| version = "2.33.3" | version = "2.33.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | dependencies = [ | ||||
| "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", | "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)", | "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)", | "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)", | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| version = "0.4.3" | version = "0.4.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | dependencies = [ | ||||
| "adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | "adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "num-integer" | |||||
| version = "0.1.44" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||||
| dependencies = [ | |||||
| "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| ] | |||||
| [[package]] | |||||
| name = "num-traits" | name = "num-traits" | ||||
| version = "0.2.14" | version = "0.2.14" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | dependencies = [ | ||||
| "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| dependencies = [ | dependencies = [ | ||||
| "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "rhg" | name = "rhg" | ||||
| version = "0.1.0" | version = "0.1.0" | ||||
| dependencies = [ | dependencies = [ | ||||
| "chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", | "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "derive_more 0.99.11 (registry+https://github.com/rust-lang/crates.io-index)", | "derive_more 0.99.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "format-bytes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | "format-bytes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "hg-core 0.1.0", | "hg-core 0.1.0", | ||||
| "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "micro-timer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | "micro-timer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "users 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "rust-crypto" | name = "rust-crypto" | ||||
| version = "0.2.36" | version = "0.2.36" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | dependencies = [ | ||||
| "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", | "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| [[package]] | [[package]] | ||||
| name = "unicode-xid" | name = "unicode-xid" | ||||
| version = "0.2.1" | version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| [[package]] | [[package]] | ||||
| name = "users" | |||||
| version = "0.11.0" | |||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | |||||
| dependencies = [ | |||||
| "libc 0.2.81 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| ] | |||||
| [[package]] | |||||
| name = "vcpkg" | name = "vcpkg" | ||||
| version = "0.2.11" | version = "0.2.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| [[package]] | [[package]] | ||||
| name = "vec_map" | name = "vec_map" | ||||
| version = "0.8.2" | version = "0.8.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" | ||||
| "checksum bitmaps 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" | "checksum bitmaps 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" | ||||
| "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" | "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" | ||||
| "checksum bytes-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3196ba300c7bc9282a4331e878496cb3e9603a898a8f1446601317163e16ca52" | "checksum bytes-cast 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3196ba300c7bc9282a4331e878496cb3e9603a898a8f1446601317163e16ca52" | ||||
| "checksum bytes-cast-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb" | "checksum bytes-cast-derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb" | ||||
| "checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" | "checksum cc 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)" = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" | ||||
| "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" | ||||
| "checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | "checksum cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
| "checksum chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" | |||||
| "checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" | "checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" | ||||
| "checksum const_fn 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" | "checksum const_fn 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" | ||||
| "checksum cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaf3847ab963e40c4f6dd8d6be279bdf74007ae2413786a0dcbb28c52139a95" | "checksum cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaf3847ab963e40c4f6dd8d6be279bdf74007ae2413786a0dcbb28c52139a95" | ||||
| "checksum crc32fast 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" | "checksum crc32fast 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" | ||||
| "checksum crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" | "checksum crossbeam-channel 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" | ||||
| "checksum crossbeam-channel 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" | "checksum crossbeam-channel 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" | ||||
| "checksum crossbeam-deque 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" | "checksum crossbeam-deque 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" | ||||
| "checksum crossbeam-epoch 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" | "checksum crossbeam-epoch 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" | ||||
| "checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" | "checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" | ||||
| "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" | "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" | ||||
| "checksum memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" | "checksum memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" | ||||
| "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" | "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" | ||||
| "checksum memoffset 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" | "checksum memoffset 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" | ||||
| "checksum micro-timer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c" | "checksum micro-timer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c" | ||||
| "checksum micro-timer-macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e28a3473e6abd6e9aab36aaeef32ad22ae0bd34e79f376643594c2b152ec1c5d" | "checksum micro-timer-macros 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e28a3473e6abd6e9aab36aaeef32ad22ae0bd34e79f376643594c2b152ec1c5d" | ||||
| "checksum miniz_oxide 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" | "checksum miniz_oxide 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" | ||||
| "checksum num-integer 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" | |||||
| "checksum num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" | "checksum num-traits 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" | ||||
| "checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" | "checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" | ||||
| "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" | "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" | ||||
| "checksum pkg-config 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" | "checksum pkg-config 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" | ||||
| "checksum ppv-lite86 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" | "checksum ppv-lite86 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" | ||||
| "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" | "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" | ||||
| "checksum proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" | "checksum proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" | ||||
| "checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" | "checksum proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" | ||||
| "checksum termcolor 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" | "checksum termcolor 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" | ||||
| "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" | "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 thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" | ||||
| "checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" | "checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" | ||||
| "checksum twox-hash 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" | "checksum twox-hash 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" | ||||
| "checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" | "checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" | ||||
| "checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" | "checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" | ||||
| "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" | "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" | ||||
| "checksum users 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" | |||||
| "checksum vcpkg 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" | "checksum vcpkg 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" | ||||
| "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" | "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 version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" | ||||
| "checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" | "checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" | ||||
| "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" | "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" | ||||
| "checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | "checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | ||||
| "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||||
| "checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | "checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" | ||||
| "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||||
| "checksum zstd 0.5.3+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8" | "checksum zstd 0.5.3+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8" | ||||
| "checksum zstd-safe 2.0.5+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055" | "checksum zstd-safe 2.0.5+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055" | ||||
| "checksum zstd-sys 1.4.17+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b" | "checksum zstd-sys 1.4.17+zstd.1.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b" | ||||
| const MIN_ENTRY_SIZE: usize = 17; | const MIN_ENTRY_SIZE: usize = 17; | ||||
| type ParseResult<'a> = ( | type ParseResult<'a> = ( | ||||
| &'a DirstateParents, | &'a DirstateParents, | ||||
| Vec<(&'a HgPath, DirstateEntry)>, | Vec<(&'a HgPath, DirstateEntry)>, | ||||
| Vec<(&'a HgPath, &'a HgPath)>, | Vec<(&'a HgPath, &'a HgPath)>, | ||||
| ); | ); | ||||
| pub fn parse_dirstate_parents( | |||||
| contents: &[u8], | |||||
| ) -> Result<&DirstateParents, HgError> { | |||||
| let (parents, _rest) = DirstateParents::from_bytes(contents) | |||||
| .map_err(|_| HgError::corrupted("Too little data for dirstate."))?; | |||||
| Ok(parents) | |||||
| } | |||||
| #[timed] | #[timed] | ||||
| pub fn parse_dirstate(mut contents: &[u8]) -> Result<ParseResult, HgError> { | pub fn parse_dirstate(mut contents: &[u8]) -> Result<ParseResult, HgError> { | ||||
| let mut copies = Vec::new(); | let mut copies = Vec::new(); | ||||
| let mut entries = Vec::new(); | let mut entries = Vec::new(); | ||||
| let (parents, rest) = DirstateParents::from_bytes(contents) | let (parents, rest) = DirstateParents::from_bytes(contents) | ||||
| .map_err(|_| HgError::corrupted("Too little data for dirstate."))?; | .map_err(|_| HgError::corrupted("Too little data for dirstate."))?; | ||||
| contents = rest; | contents = rest; | ||||
| // The undescore prefix silences the "never used" warning. Remove before | // The undescore prefix silences the "never used" warning. Remove before | ||||
| // using. | // using. | ||||
| pub fn _working_directory_vfs(&self) -> Vfs<'_> { | pub fn _working_directory_vfs(&self) -> Vfs<'_> { | ||||
| Vfs { | Vfs { | ||||
| base: &self.working_directory, | base: &self.working_directory, | ||||
| } | } | ||||
| } | } | ||||
| pub fn dirstate_parents( | |||||
| &self, | |||||
| ) -> Result<crate::dirstate::DirstateParents, HgError> { | |||||
| let dirstate = self.hg_vfs().mmap_open("dirstate")?; | |||||
| let parents = | |||||
| crate::dirstate::parsers::parse_dirstate_parents(&dirstate)?; | |||||
| Ok(parents.clone()) | |||||
| } | |||||
| } | } | ||||
| impl Vfs<'_> { | impl Vfs<'_> { | ||||
| pub fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { | pub fn join(&self, relative_path: impl AsRef<Path>) -> PathBuf { | ||||
| self.base.join(relative_path) | self.base.join(relative_path) | ||||
| } | } | ||||
| pub fn read( | pub fn read( | ||||
| pub(crate) fn strip_suffix<'a>(s: &'a str, suffix: &str) -> Option<&'a str> { | pub(crate) fn strip_suffix<'a>(s: &'a str, suffix: &str) -> Option<&'a str> { | ||||
| if s.ends_with(suffix) { | if s.ends_with(suffix) { | ||||
| Some(&s[..s.len() - suffix.len()]) | Some(&s[..s.len() - suffix.len()]) | ||||
| } else { | } else { | ||||
| None | None | ||||
| } | } | ||||
| } | } | ||||
| #[cfg(unix)] | |||||
| pub fn shell_quote(value: &[u8]) -> Vec<u8> { | |||||
| // TODO: Use the `matches!` macro when we require Rust 1.42+ | |||||
| if value.iter().all(|&byte| match byte { | |||||
| b'a'..=b'z' | |||||
| | b'A'..=b'Z' | |||||
| | b'0'..=b'9' | |||||
| | b'.' | |||||
| | b'_' | |||||
| | b'/' | |||||
| | b'+' | |||||
| | b'-' => true, | |||||
| _ => false, | |||||
| }) { | |||||
| value.to_owned() | |||||
| } else { | |||||
| let mut quoted = Vec::with_capacity(value.len() + 2); | |||||
| quoted.push(b'\''); | |||||
| for &byte in value { | |||||
| if byte == b'\'' { | |||||
| quoted.push(b'\\'); | |||||
| } | |||||
| quoted.push(byte); | |||||
| } | |||||
| quoted.push(b'\''); | |||||
| quoted | |||||
| } | |||||
| } | |||||
| pub fn current_dir() -> Result<std::path::PathBuf, HgError> { | pub fn current_dir() -> Result<std::path::PathBuf, HgError> { | ||||
| std::env::current_dir().map_err(|error| HgError::IoError { | std::env::current_dir().map_err(|error| HgError::IoError { | ||||
| error, | error, | ||||
| context: IoErrorContext::CurrentDir, | context: IoErrorContext::CurrentDir, | ||||
| }) | }) | ||||
| } | } | ||||
| pub fn current_exe() -> Result<std::path::PathBuf, HgError> { | pub fn current_exe() -> Result<std::path::PathBuf, HgError> { | ||||
| std::env::current_exe().map_err(|error| HgError::IoError { | std::env::current_exe().map_err(|error| HgError::IoError { | ||||
| error, | error, | ||||
| context: IoErrorContext::CurrentExe, | context: IoErrorContext::CurrentExe, | ||||
| }) | }) | ||||
| } | } | ||||
| [package] | [package] | ||||
| name = "rhg" | name = "rhg" | ||||
| version = "0.1.0" | version = "0.1.0" | ||||
| authors = [ | authors = [ | ||||
| "Antoine Cezar <antoine.cezar@octobus.net>", | "Antoine Cezar <antoine.cezar@octobus.net>", | ||||
| "Raphaël Gomès <raphael.gomes@octobus.net>", | "Raphaël Gomès <raphael.gomes@octobus.net>", | ||||
| ] | ] | ||||
| edition = "2018" | edition = "2018" | ||||
| [dependencies] | [dependencies] | ||||
| hg-core = { path = "../hg-core"} | hg-core = { path = "../hg-core"} | ||||
| chrono = "0.4.19" | |||||
| clap = "2.33.1" | clap = "2.33.1" | ||||
| derive_more = "0.99" | derive_more = "0.99" | ||||
| log = "0.4.11" | log = "0.4.11" | ||||
| micro-timer = "0.3.1" | micro-timer = "0.3.1" | ||||
| env_logger = "0.7.1" | env_logger = "0.7.1" | ||||
| format-bytes = "0.2.0" | format-bytes = "0.2.0" | ||||
| users = "0.11.0" | |||||
| //! Logging for repository events, including commands run in the repository. | |||||
| use crate::CliInvocation; | |||||
| use format_bytes::format_bytes; | |||||
| use hg::errors::HgError; | |||||
| use hg::repo::Repo; | |||||
| use hg::utils::{files::get_bytes_from_os_str, shell_quote}; | |||||
| const ONE_MEBIBYTE: u64 = 1 << 20; | |||||
| // TODO: somehow keep defaults in sync with `configitem` in `hgext/blackbox.py` | |||||
| const DEFAULT_MAX_SIZE: u64 = ONE_MEBIBYTE; | |||||
| const DEFAULT_MAX_FILES: u32 = 7; | |||||
| // Python does not support %.3f, only %f | |||||
| const DEFAULT_DATE_FORMAT: &str = "%Y/%m/%d %H:%M:%S%.3f"; | |||||
| type DateTime = chrono::DateTime<chrono::Local>; | |||||
| pub struct ProcessStartTime { | |||||
| /// For measuring duration | |||||
| monotonic_clock: std::time::Instant, | |||||
| /// For formatting with year, month, day, etc. | |||||
| calendar_based: DateTime, | |||||
| } | |||||
| impl ProcessStartTime { | |||||
| pub fn now() -> Self { | |||||
| Self { | |||||
| monotonic_clock: std::time::Instant::now(), | |||||
| calendar_based: chrono::Local::now(), | |||||
| } | |||||
| } | |||||
| } | |||||
| pub struct Blackbox<'a> { | |||||
| process_start_time: &'a ProcessStartTime, | |||||
| /// Do nothing if this is `None` | |||||
| configured: Option<ConfiguredBlackbox<'a>>, | |||||
| } | |||||
| struct ConfiguredBlackbox<'a> { | |||||
| repo: &'a Repo, | |||||
| max_size: u64, | |||||
| max_files: u32, | |||||
| date_format: &'a str, | |||||
| } | |||||
| impl<'a> Blackbox<'a> { | |||||
| pub fn new( | |||||
| invocation: &'a CliInvocation<'a>, | |||||
| process_start_time: &'a ProcessStartTime, | |||||
| ) -> Result<Self, HgError> { | |||||
| let configured = if let Ok(repo) = invocation.repo { | |||||
| let config = invocation.config(); | |||||
| if config.get(b"extensions", b"blackbox").is_none() { | |||||
| // The extension is not enabled | |||||
| None | |||||
| } else { | |||||
| // TODO!date-format config. Quotes? | |||||
Alphare: You've got a NBSP here ;) | |||||
SimonSapinAuthorUnsubmitted Done Right. This comment was obsolete anyway so I’ve removed it. (date-format is part of this commit and there’s not quoting in config syntax outside of list-values, see previous commit.) SimonSapin: Right. This comment was obsolete anyway so I’ve removed it. (`date-format` is part of this… | |||||
| Some(ConfiguredBlackbox { | |||||
| repo, | |||||
| max_size: config | |||||
| .get_byte_size(b"blackbox", b"maxsize")? | |||||
| .unwrap_or(DEFAULT_MAX_SIZE), | |||||
| max_files: config | |||||
| .get_u32(b"blackbox", b"maxfiles")? | |||||
| .unwrap_or(DEFAULT_MAX_FILES), | |||||
| date_format: config | |||||
| .get_str(b"blackbox", b"date-format")? | |||||
| .unwrap_or(DEFAULT_DATE_FORMAT), | |||||
| }) | |||||
| } | |||||
| } else { | |||||
| // Without a local repository there’s no `.hg/blackbox.log` to | |||||
| // write to. | |||||
| None | |||||
| }; | |||||
| Ok(Self { | |||||
| process_start_time, | |||||
| configured, | |||||
| }) | |||||
| } | |||||
| pub fn log_command_start(&self) { | |||||
| if let Some(configured) = &self.configured { | |||||
| let message = format_bytes!(b"(rust) {}", format_cli_args()); | |||||
| configured.log(&self.process_start_time.calendar_based, &message); | |||||
| } | |||||
| } | |||||
| pub fn log_command_end(&self, exit_code: i32) { | |||||
| if let Some(configured) = &self.configured { | |||||
| let now = chrono::Local::now(); | |||||
| let duration = self | |||||
| .process_start_time | |||||
| .monotonic_clock | |||||
| .elapsed() | |||||
| .as_secs_f64(); | |||||
| let message = format_bytes!( | |||||
| b"(rust) {} exited {} after {} seconds", | |||||
| format_cli_args(), | |||||
| exit_code, | |||||
| format_bytes::Utf8(format_args!("{:.03}", duration)) | |||||
| ); | |||||
| configured.log(&now, &message); | |||||
| } | |||||
| } | |||||
| } | |||||
| impl ConfiguredBlackbox<'_> { | |||||
| fn log(&self, date_time: &DateTime, message: &[u8]) { | |||||
| let date = format_bytes::Utf8(date_time.format(self.date_format)); | |||||
| let user = users::get_current_username().map(get_bytes_from_os_str); | |||||
| let user = user.as_deref().unwrap_or(b"???"); | |||||
AlphareUnsubmitted Not Done Problem with this is that it conflicts with .t output. Or was it intentional? Alphare: Problem with this is that it conflicts with `.t` output. Or was it intentional? | |||||
SimonSapinAuthorUnsubmitted Done Oh do you mean that (glob) expected output in .t files makes it hard to expect a literal ? character? https://docs.rs/users/0.11.0/users/fn.get_current_username.html says “This function to return None if the current user does not exist, which could happen if they were deleted after the program started running.” so I don’t expect this ??? fallback to show up a lot in practice and I think it’s not worth testing it. SimonSapin: Oh do you mean that `(glob)` expected output in `.t` files makes it hard to expect a literal `? | |||||
AlphareUnsubmitted Not Done I don't think it's worth testing either, I just meant I would have chosen a different set of characters just to avoid confusion. It's not a dealbreaker. Alphare: I don't think it's worth testing either, I just meant I would have chosen a different set of… | |||||
| let rev = format_bytes::Utf8(match self.repo.dirstate_parents() { | |||||
| Ok(parents) if parents.p2 == hg::revlog::node::NULL_NODE => { | |||||
| format!("{:x}", parents.p1) | |||||
| } | |||||
| Ok(parents) => format!("{:x}+{:x}", parents.p1, parents.p2), | |||||
| Err(_dirstate_corruption_error) => { | |||||
| // TODO: log a non-fatal warning to stderr | |||||
| "???".to_owned() | |||||
| } | |||||
| }); | |||||
| let pid = std::process::id(); | |||||
| let line = format_bytes!( | |||||
| b"{} {} @{} ({})> {}\n", | |||||
| date, | |||||
| user, | |||||
| rev, | |||||
| pid, | |||||
| message | |||||
| ); | |||||
| let result = | |||||
| hg::logging::LogFile::new(self.repo.hg_vfs(), "blackbox.log") | |||||
| .max_size(Some(self.max_size)) | |||||
| .max_files(self.max_files) | |||||
| .write(&line); | |||||
| match result { | |||||
| Ok(()) => {} | |||||
| Err(_io_error) => { | |||||
| // TODO: log a non-fatal warning to stderr | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| fn format_cli_args() -> Vec<u8> { | |||||
| let mut args = std::env::args_os(); | |||||
| let _ = args.next(); // Skip the first (or zeroth) arg, the name of the `rhg` executable | |||||
| let mut args = args.map(|arg| shell_quote(&get_bytes_from_os_str(arg))); | |||||
| let mut formatted = Vec::new(); | |||||
| if let Some(arg) = args.next() { | |||||
| formatted.extend(arg) | |||||
| } | |||||
| for arg in args { | |||||
| formatted.push(b' '); | |||||
| formatted.extend(arg) | |||||
| } | |||||
| formatted | |||||
| } | |||||
| extern crate log; | extern crate log; | ||||
| use crate::ui::Ui; | use crate::ui::Ui; | ||||
| use clap::App; | use clap::App; | ||||
| use clap::AppSettings; | use clap::AppSettings; | ||||
| use clap::Arg; | use clap::Arg; | ||||
| use clap::ArgMatches; | use clap::ArgMatches; | ||||
| use format_bytes::format_bytes; | use format_bytes::format_bytes; | ||||
| use hg::config::Config; | use hg::config::Config; | ||||
| use hg::repo::{Repo, RepoError}; | use hg::repo::{Repo, RepoError}; | ||||
| use std::path::{Path, PathBuf}; | use std::path::{Path, PathBuf}; | ||||
| mod blackbox; | |||||
| mod error; | mod error; | ||||
| mod exitcode; | mod exitcode; | ||||
| mod ui; | mod ui; | ||||
| use error::CommandError; | use error::CommandError; | ||||
| fn add_global_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { | fn add_global_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { | ||||
| app.arg( | app.arg( | ||||
| Arg::with_name("repository") | Arg::with_name("repository") | ||||
| .takes_value(true) | .takes_value(true) | ||||
| // Ok: `--config section.key1=val --config section.key2=val2` | // Ok: `--config section.key1=val --config section.key2=val2` | ||||
| .multiple(true) | .multiple(true) | ||||
| // Not ok: `--config section.key1=val section.key2=val2` | // Not ok: `--config section.key1=val section.key2=val2` | ||||
| .number_of_values(1), | .number_of_values(1), | ||||
| ) | ) | ||||
| } | } | ||||
| fn main_with_result(ui: &ui::Ui) -> Result<(), CommandError> { | fn main_with_result( | ||||
| ui: &ui::Ui, | |||||
| process_start_time: &blackbox::ProcessStartTime, | |||||
| ) -> Result<(), CommandError> { | |||||
| env_logger::init(); | env_logger::init(); | ||||
| let app = App::new("rhg") | let app = App::new("rhg") | ||||
| .setting(AppSettings::AllowInvalidUtf8) | .setting(AppSettings::AllowInvalidUtf8) | ||||
| .setting(AppSettings::SubcommandRequired) | .setting(AppSettings::SubcommandRequired) | ||||
| .setting(AppSettings::VersionlessSubcommands) | .setting(AppSettings::VersionlessSubcommands) | ||||
| .version("0.0.1"); | .version("0.0.1"); | ||||
| let app = add_global_args(app); | let app = add_global_args(app); | ||||
| let app = add_subcommand_args(app); | let app = add_subcommand_args(app); | ||||
| Ok(repo) => Ok(repo), | Ok(repo) => Ok(repo), | ||||
| Err(RepoError::NotFound { at }) if repo_path.is_none() => { | Err(RepoError::NotFound { at }) if repo_path.is_none() => { | ||||
| // Not finding a repo is not fatal yet, if `-R` was not given | // Not finding a repo is not fatal yet, if `-R` was not given | ||||
| Err(NoRepoInCwdError { cwd: at }) | Err(NoRepoInCwdError { cwd: at }) | ||||
| } | } | ||||
| Err(error) => return Err(error.into()), | Err(error) => return Err(error.into()), | ||||
| }; | }; | ||||
| run(&CliInvocation { | let invocation = CliInvocation { | ||||
| ui, | ui, | ||||
| subcommand_args, | subcommand_args, | ||||
| non_repo_config, | non_repo_config, | ||||
| repo: repo.as_ref(), | repo: repo.as_ref(), | ||||
| }) | }; | ||||
| let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?; | |||||
| blackbox.log_command_start(); | |||||
| let result = run(&invocation); | |||||
| blackbox.log_command_end(exit_code(&result)); | |||||
| result | |||||
| } | } | ||||
| fn main() { | fn main() { | ||||
| // Run this first, before we find out if the blackbox extension is even | |||||
| // enabled, in order to include everything in-between in the duration | |||||
| // measurements. Reading config files can be slow if they’re on NFS. | |||||
| let process_start_time = blackbox::ProcessStartTime::now(); | |||||
| let ui = ui::Ui::new(); | let ui = ui::Ui::new(); | ||||
| let exit_code = match main_with_result(&ui) { | let result = main_with_result(&ui, &process_start_time); | ||||
| if let Err(CommandError::Abort { message }) = &result { | |||||
| if !message.is_empty() { | |||||
| // Ignore errors when writing to stderr, we’re already exiting | |||||
| // with failure code so there’s not much more we can do. | |||||
| let _ = ui.write_stderr(&format_bytes!(b"abort: {}\n", message)); | |||||
| } | |||||
| } | |||||
| std::process::exit(exit_code(&result)) | |||||
| } | |||||
| fn exit_code(result: &Result<(), CommandError>) -> i32 { | |||||
| match result { | |||||
| Ok(()) => exitcode::OK, | Ok(()) => exitcode::OK, | ||||
| Err(CommandError::Abort { .. }) => exitcode::ABORT, | |||||
| // Exit with a specific code and no error message to let a potential | // Exit with a specific code and no error message to let a potential | ||||
| // wrapper script fallback to Python-based Mercurial. | // wrapper script fallback to Python-based Mercurial. | ||||
| Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED, | Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED, | ||||
| Err(CommandError::Abort { message }) => { | |||||
| if !message.is_empty() { | |||||
| // Ignore errors when writing to stderr, we’re already exiting | |||||
| // with failure code so there’s not much more we can do. | |||||
| let _ = | |||||
| ui.write_stderr(&format_bytes!(b"abort: {}\n", message)); | |||||
| } | |||||
| exitcode::ABORT | |||||
| } | } | ||||
| }; | |||||
| std::process::exit(exit_code) | |||||
| } | } | ||||
| macro_rules! subcommands { | macro_rules! subcommands { | ||||
| ($( $command: ident )+) => { | ($( $command: ident )+) => { | ||||
| mod commands { | mod commands { | ||||
| $( | $( | ||||
| pub mod $command; | pub mod $command; | ||||
| )+ | )+ | ||||
| And check that basic rhg commands work with sharing | And check that basic rhg commands work with sharing | ||||
| $ cd repo5 | $ cd repo5 | ||||
| $ rhg files | $ rhg files | ||||
| a | a | ||||
| $ rhg cat -r 0 a | $ rhg cat -r 0 a | ||||
| a | a | ||||
| The blackbox extension is supported | |||||
| $ echo "[extensions]" >> $HGRCPATH | |||||
| $ echo "blackbox =" >> $HGRCPATH | |||||
| $ echo "[blackbox]" >> $HGRCPATH | |||||
| $ echo "maxsize = 1" >> $HGRCPATH | |||||
| $ rhg files > /dev/null | |||||
| $ cat .hg/blackbox.log | |||||
| ????/??/?? ??:??:??.??? * @d3873e73d99ef67873dac33fbcc66268d5d2b6f4 (*)> (rust) files exited 0 after 0.??? seconds (glob) | |||||
| $ cat .hg/blackbox.log.1 | |||||
| ????/??/?? ??:??:??.??? * @d3873e73d99ef67873dac33fbcc66268d5d2b6f4 (*)> (rust) files (glob) | |||||
You've got a NBSP here ;)