Commit graph

16897 commits

Author SHA1 Message Date
Anthony Towns
8a9817d175 [tests] Use regtest section in functional tests configs 2018-04-11 23:15:28 +10:00
Anthony Towns
30f94074c8 [tests] Unit tests for config file sections 2018-04-11 23:15:28 +10:00
Anthony Towns
95eb66d584 ArgsManager: support config file sections 2018-04-11 23:15:28 +10:00
Anthony Towns
4d34fcc713 ArgsManager: drop m_negated_args
When a -nofoo option is seen, instead of adding it to a separate
set of negated args, set the arg as being an empty vector of strings.

This changes the behaviour in some ways:
 - -nofoo=0 still sets foo=1 but no longer treats it as a negated arg
 - -nofoo=1 -foo=2 has GetArgs() return [2] rather than [2,0]
 - "foo=2 \n -nofoo=1" in a config file no longer returns [2,0], just [0]
 - GetArgs returns an empty vector for negated args
2018-04-11 23:15:28 +10:00
Wladimir J. van der Laan
b1fdfc1a8c
Merge #12920: test: Fix sign for expected values
c55aa4f test: Fix sign for expected values (Karl-Johan Alm)

Pull request description:

  A number of `BOOST_CHECK_EQUAL` calls would result in warnings about signs.

  This PR fixes signedness for all expectation values, sometimes resulting in `int` → `unsigned int`. No other code changes besides adding/removing `U` to/from values.

  Running `make &> make_output_...` on master versus on this PR:
  ```
  $ wc make_output_*
      1464    5925   90357 make_output_master
       613    1469   28370 make_output_signfixed
  ```
  More than halves the output lines from compiling.

Tree-SHA512: b06c9fb81704fd32a6a61fe7b2ceb5f1bb381e9873d79e13d7e4d26bbd9b67c9725a84e6fb2903bcda775aea2a792e544b0799d36735c19f5d1c7225e8c6d14e
2018-04-11 15:01:34 +02:00
Henrik Jonsson
aff16fd511 depends: Add 'make clean' and 'make clean-all' rules
It's useful to have a standard way to clean up the work done by the
depends system when testing changes to it.

The `make clean-all` rule removes build artifacts for all
supported architectures (in addition to sources/), while `make clean`
only removes artifacts for current architecture (`BUILD`).
2018-04-11 12:49:44 +00:00
Wladimir J. van der Laan
f15b72f482
Merge #12650: gui: Fix issue: "default port not shown correctly in settings dialog"
40c5886 Fix illegal default `addProxy` and `addrSeparateProxyTor` settings. (251)

Pull request description:

  In f05d349 the value of the `addrProxy` and `addrSeparateProxyTor` settings is set to an illegal default value, because the value of `DEFAULT_GUI_PROXY_PORT ` is passed to the `fieldWidth` parameter of the `QString QString::arg(const QString &a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' )) const` method:

  29fad97c32/src/qt/optionsmodel.cpp (L129)

  29fad97c32/src/qt/optionsmodel.cpp (L139)

  This will create a default proxy setting that consists of 9053 characters and ends with the string `127.0.0.1:%2`.

  This PR attempts to resolve #12623 by setting the correct value for the `addrProxy` and `addrSeparateProxyTor` settings (i) if the proxy setting does not exist; or (ii) if the proxy setting has an illegal value caused by to the aforementioned bug.

  The second condition is *only* relevant if we don't want Bitcoin Core 0.16.0 users to explicitly reset their settings to see the correct default proxy port value.

Tree-SHA512: 3dc3de2eb7da831f6e318797df67341ced2076b48f9b561c73677bf6beb67b259d8e413095f290356fb92e32e4e8162d48accbc575c4e612060fd5d6dde7ac8d
2018-04-11 14:44:24 +02:00
Wladimir J. van der Laan
7b6041d1a7
Merge #12916: Introduce BigEndian wrapper and use it for netaddress ports
ece88fd Introduce BigEndian wrapper and use it for netaddress ports (Pieter Wuille)

Pull request description:

  This is another small improvement taken from #10785.

  Instead of manually converting from/to BE format in the `CService` serializer, provide a generic way in serialize.h to serialize BE data (only 16 bits for now).

Tree-SHA512: bd67cf7eed465dad08551fb62f659e755e0691e4597a9f59d285d2b79975b50e5710d35a34a185b5ad232e1deda9a4946615f9132b1ed7d96ed8087f73ace66b
2018-04-11 14:23:58 +02:00
practicalswift
0000d8f727 Document how FlushStateMode::NONE is handled 2018-04-11 12:45:59 +02:00
practicalswift
2311c7cc86 Call FlushStateToDisk(...) regardless of fCheckForPruning
FlushStateToDisk(...) won't do anything besides check if we need to prune if
FLUSH_STATE_NONE is given. We avoid reading the variable fCheckForPruning
which is guarded by the mutex cs_LastBlockFile.
2018-04-11 12:40:08 +02:00
Ben Woosley
459ea5836e
rpc: Drop redundant testing of signrawtransaction prevtxs args
These other types are already tested on line 736.
2018-04-11 03:33:01 -07:00
Wladimir J. van der Laan
807d2ac186
Merge #12941: [Trivial] Ignore macOS daemon() depracation warning
12e7c55 Ignore macOS daemon() depracation warning (Jonas Schnelli)

Pull request description:

  `daemon()` is deprecated on OSX since 10.5 (should migrate to `posix_spawn()`). There are no signs `daemon()` will get removed by Apple.

Tree-SHA512: d5bcdc5d6b507576e0358906a73f9c766f2072f4a9aef6bdc559e10dbec95337ffa50a1ccb60f7197591e2e74f87c74c13387de880aaedc6dbf3796253f69561
2018-04-11 11:43:23 +02:00
Wladimir J. van der Laan
9b3370d1c6
Merge #12892: [wallet] [rpc] introduce 'label' API for wallet
41ba061 [docs] Add release notes for wallet 'label' API. (John Newbery)
189e0ef [wallet] [rpc] introduce 'label' API for wallet (Wladimir J. van der Laan)

Pull request description:

  Add label API to wallet RPC.

  This is one step towards #3816 ("Remove bolt-on account system") although it doesn't
  actually remove anything yet.

  These initially mirror the account functions, with the following differences:

  - These functions aren't DEPRECATED in the help
  - Help mentions 'label' instead of accounts. In the language used, labels are
    associated with addresses, instead of addresses associated with labels. (unlike
    with accounts.)
  - Labels have no balance
    - No balances in `listlabels`
    - `listlabels` has no minconf or watchonly argument
  - Like in the GUI, labels can be set on any address, not just receiving addreses
  - Unlike accounts, labels can be deleted.
    Being unable to delete them is a common annoyance (see #1231).
    Currently only by reassigning all addresses using `setlabel`, but an explicit
    call `deletelabel` which assigns all address to the default label may make
    sense.

Tree-SHA512: 45cc313c68ad529ce3a15c02181d2ab0083a7e14fe824e2cde34972713fecce512e3d4b9aa46db5355f2baa857c44b234d4fe9709225bc23c7ebbc0e03febbf5
2018-04-11 11:41:20 +02:00
Jonas Schnelli
12e7c558af
Ignore macOS daemon() depracation warning 2018-04-11 10:19:44 +02:00
Anthony Towns
3673ca36ef ArgsManager: keep command line and config file arguments separate 2018-04-11 18:13:54 +10:00
Karl-Johan Alm
c55aa4f27d
test: Fix sign for expected values
A number of BOOST_CHECK_EQUAL calls would result in warnings about signs.
2018-04-11 13:39:41 +09:00
Ben Woosley
3450a9b25c
Extract consts for WITNESS_V0 hash sizes 2018-04-10 20:13:32 -07:00
John Newbery
41ba061804 [docs] Add release notes for wallet 'label' API. 2018-04-10 19:27:28 -04:00
Wladimir J. van der Laan
189e0ef33e [wallet] [rpc] introduce 'label' API for wallet
Add label API to wallet RPC.

This is one step towards #3816 ("Remove bolt-on account system") although it doesn't
actually remove anything yet.

These initially mirror the account functions, with the following differences:

- These functions aren't DEPRECATED in the help
- Help mentions 'label' instead of accounts. In the language used, labels are
  associated with addresses, instead of addresses associated with labels. (unlike
  with accounts.)
- Labels have no balance
  - No balances in `listlabels`
  - `listlabels` has no minconf or watchonly argument
- Like in the GUI, labels can be set on any address, not just receiving addreses
- Unlike accounts, labels can be deleted.
  Being unable to delete them is a common annoyance (see #1231).
  Currently only by reassigning all addresses using `setlabel`, but an explicit
  call `deletelabel` which assigns all address to the default label may make
  sense.

Thanks to Pierre Rochard for test fixes.
2018-04-10 19:27:22 -04:00
251
40c58866c7 Fix illegal default addProxy and addrSeparateProxyTor settings. 2018-04-10 22:22:55 +02:00
MarcoFalke
fad0fc3c9a
Refine travis check for duplicate includes
This partially reverts commit c36b720d00.
2018-04-10 15:12:42 -04:00
Wladimir J. van der Laan
0a8054e7cd
Merge #12731: Support serialization as another type without casting
818dc74 Support serialization as another type without casting (Pieter Wuille)

Pull request description:

  This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically.

  This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved.

  This is a redo of #12712, using a slightly different interface.

Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
2018-04-10 20:54:33 +02:00
Wladimir J. van der Laan
a84b056d5f
Merge #12749: [wallet] feebumper: discard change outputs below discard rate
f526046 adapt bumpfee change discard test to be more strict and add note on p2sh discrep (Gregory Sanders)
5805d6f feebumper: discard change outputs below discard rate (Gregory Sanders)

Pull request description:

  The "discard rate" is the concept we use to ensure the wallet isnt creating not so useful just-above-relay dust.

  Outside of bumpfee previous to this PR, and manually creating such an output, the wallet will never make change outputs of that size, preferring to send them to fees instead.

  "Worst case" for the user is that users pay a slightly higher feerate than they were expecting, which is already a possibility with relay dust.

Tree-SHA512: dd69351810dc1709437602e7db1be46e4e905ccd8e16d03952de8b4c1fdbf9cb7e6c99968930896baf6b5c7cb005a03ec0506a2669d22e21e32982e60329606b
2018-04-10 19:35:51 +02:00
Pieter Wuille
be67831210 Make DummySignatureCreator a singleton 2018-04-10 09:29:17 -07:00
Pieter Wuille
190b8d2dcf Make BaseSignatureCreator a pure interface 2018-04-10 09:29:17 -07:00
MarcoFalke
8d651ae320
Merge #12932: wallet: Remove redundant lambda function arg in handleTransactionChanged
9b9d717263 wallet: Remove redundant lambda function arg in handleTransactionChanged (Wladimir J. van der Laan)

Pull request description:

  Makes the build warning-clean again here:

      bitcoin/src/interfaces/wallet.cpp:425:18: warning: lambda capture 'this' is not used [-Wunused-lambda-capture]
                  [fn, this](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); }));
                       ^

Tree-SHA512: 82362c8fb3638246a6c3b28998165eed8a6490f9e13cf2741fb2776ef7f82a1c0bb5ea1f58b7ff842bd59c9830f59f5a478fb63860693055c4d8dd72a94d8a5a
2018-04-10 10:57:10 -04:00
Wladimir J. van der Laan
5ca1509d6a
Merge #12854: Add P2P, Network, and Qt categories to the desktop icon
b63f23c Add P2P, Network, and Qt categories to the desktop icon (Luke Dashjr)

Pull request description:

Tree-SHA512: 10526bfb4b559ce43b28c6c82fa615cd167162e5c487025ade51fb6b67389a65d8b43138228ced49d6d6cdc8ac87654a7b76673e92e7b43b5a09c81642d59145
2018-04-10 15:33:57 +02:00
Wladimir J. van der Laan
ebd786b72a
Merge #12852: [doc] devtools: Setup ots git integration
fa385c3 [doc] devtools: Setup ots git integration (MarcoFalke)

Pull request description:

  Document the simple steps on how to set up ots git integration.

Tree-SHA512: 1b9f99bfaa6cd9dc581243d3a3584301645e95450acc3b5898dcdb53849569de16bb8ef2676b18f6b8dd402de10aee80119e15c1b28cef36f17ad121cbba2ba3
2018-04-10 15:29:10 +02:00
Wladimir J. van der Laan
9b9d717263 wallet: Remove redundant lambda function arg in handleTransactionChanged
Makes the build warning-clean again here:

    bitcoin/src/interfaces/wallet.cpp:425:18: warning: lambda capture 'this' is not used [-Wunused-lambda-capture]
                [fn, this](CWallet*, const uint256& txid, ChangeType status) { fn(txid, status); }));
                     ^
2018-04-10 15:23:37 +02:00
Wladimir J. van der Laan
dd1ca9e0b3
Merge #12926: Run unit tests in parallel
7ef9cd8 Increase entropy in test temp directory name (Pieter Wuille)
f6dfb0f Reorder travis builds (Pieter Wuille)
156db42 tests: run tests in parallel (Cory Fields)
66f3255 tests: split up actual tests and helper files (Cory Fields)

Pull request description:

  This runs the unit tests (`src/test/test_bitcoin`) in 4 separate simultaneous processes, significantly speeding up some Travis runs (over 2x for win32).

  This uses an approach by @theuni that relies on `make` as the mechanism for distributing tests over processes (through `-j`). For every test .cpp file, we search for `BOOST_FIXTURE_TEST_SUITE` or `BOOST_AUTO_TEST_SUITE`, and then invoke the test binary for just that suite (using `-t`). The (verbose) output is stored in a temporary file, and only shown in the case of failure.

  Some makefile reshuffling is necessary to avoid trying to run tests from `src/test/test_bitcoin.cpp` for example, which contains framework/utility code but no real tests.

  Finally, order the Travis jobs from slow to fast (apart from the arm/doc job which goes first, for fast failure). This should help reducing the total wall clock time before opening a PR and finishing Travis, in case where not all jobs are started simultaneously.

  This is an alternative to #12831.

Tree-SHA512: 9f82eb4ade14ac859618da533c7d9df2aa9f5592a076dcc4939beeffd109eda33f7d5480d8f50c0d8b23bf3099759e9f3a2d4c78efb5b66b04569b39b354c185
2018-04-10 14:27:18 +02:00
Pieter Wuille
7ef9cd8491 Increase entropy in test temp directory name 2018-04-09 19:59:29 -04:00
Pieter Wuille
f6dfb0f504 Reorder travis builds 2018-04-09 19:59:05 -04:00
Cory Fields
156db42c3f tests: run tests in parallel 2018-04-09 19:56:25 -04:00
Cory Fields
66f32551bd tests: split up actual tests and helper files 2018-04-09 19:55:49 -04:00
MarcoFalke
727175a08d
Merge #12902: [qa] Handle potential cookie race when starting node
75d0e4c544 [qa] Delete cookie file before starting node (Suhas Daftuar)

Pull request description:

  When a node is restarted during a test after an unclean shutdown (such
  as with -dbcrashratio), it's possible an old cookie file was left
  behind. This can cause a race condition when restarting the node, where
  the test framework might try to connect using credentials from the
  old cookie file, just as the node will generate new credentials and
  overwrite the old file.

  Delete any such cookie file if present prior to startup.

Tree-SHA512: ae1e8bf8fd20e07c32b0715025693bb28b0e3dd34f328cae4346abf579b0c97b5db1c02782e1c46b7a3b6058d268b6d46b668e847658a6eed0be857ffb0d65dc
2018-04-09 19:11:08 -04:00
MarcoFalke
06ead15050
Merge #12927: Docs: fixed link, replaced QT with Qt
7039319db5 Docs: fixed link, replaced QT with Qt (Darko Janković)

Pull request description:

Tree-SHA512: 6c071189b4c030d03d3d09535333d2ed7115fba07ee2561591124c2063041966cc8012e4d8416c3dda155f2df5e15b8f772712cac35b4d266b50c48f4d74b6e4
2018-04-09 19:09:56 -04:00
MarcoFalke
7ee6fc58f8
Merge #12845: Trivial: Add logging line in init.cpp that was accidentally removed with #10762
23abfb7b7f added logging line back that was accidentally removed with #10762 (Steve Lee)

Pull request description:

  I made the change based off of the DummyWalletInit refactor commit. I can rebase once that is merged.

  I built with wallet disabled and debug enabled. I then confirmed in the debug output that the logging line I added back indeed printed.

Tree-SHA512: 94133aa3add9c73fa33fcc51b89fe0bc58344ab8a0ca63898961932a57b1f14b79e8113d3aeae116e0b91809f5660c636a565ea4681368c7ba85890a30e70589
2018-04-09 19:08:02 -04:00
Darko Janković
7039319db5
Docs: fixed link, replaced QT with Qt 2018-04-09 22:55:36 +02:00
Steve Lee
23abfb7b7f added logging line back that was accidentally removed with #10762 2018-04-09 12:21:25 -07:00
MarcoFalke
cf8073f8d1
Merge #12917: qa: Windows fixups for functional tests
fab9095d40 qa: Windows fixups for functional tests (MarcoFalke)

Pull request description:

  Just two minor fixups to have less errors when the tests run on native windows.
  * Strip whitespace from lines when reading from a notification file
  * Instead of clumsily creating a file with weird permissions, just create a folder for the same effect in `mempool_persist.py`

Tree-SHA512: 48a8b439f14ab9b44c5cd228cd03105e8613e703e3c2951cdf724931bc95172a9ad9bfe69fc23e73dd91b058c1352263c0ac6e8de2ceb0ebf804c8ff52bba394
2018-04-09 14:37:05 -04:00
Suhas Daftuar
75d0e4c544 [qa] Delete cookie file before starting node
If a cookie file exists in a datadir prior to node startup, it must have
been leftover from a prior unclean shutdown. As bitcoind will overwrite
it anyway, delete it before starting up to prevent the test framework
from inadvertently trying to connect using stale credentials.
2018-04-09 14:35:09 -04:00
Wladimir J. van der Laan
0700b6f778
Merge #11851: scripted-diff: Rename wallet database classes
9b0f0c5 Add m_ prefix to WalletBatch::m_batch (Russell Yanofsky)
398c6f0 Update walletdb comment after renaming. (Russell Yanofsky)
ea23945 scripted-diff: Rename wallet database classes (Russell Yanofsky)

Pull request description:

  Scripted diff to rename some wallet classes. Motivated by discussion in https://github.com/bitcoin/bitcoin/pull/11687#discussion_r155354119

  | Current          | New                 |
  | ---------------- | ------------------- |
  | CDBEnv           | BerkeleyEnvironment |
  | CDB              | BerkeleyBatch       |
  | CWalletDBWrapper | WalletDatabase      |
  | CWalletDB        | WalletBatch         |

  Berkeley\* classes are intended to contain BDB specific code, while Wallet\* classes are intended to be more backend-agnostic.

  Also renamed associated variables:

  | Current             | New             |
  | ------------------- | --------------- |
  | dbw                 | database        |
  | pwalletdb           | batch           |
  | pwalletdbEncryption | encrypted_batch |

Tree-SHA512: 372f2e24b2deb59d4792b5ed578aaf0cce51b6db41c400bef5d0c2cd7833e62ae4d4afa0f6000268d52e15b20f737c5a55f1cecf7768556a782fd8cd6fe051d9
2018-04-09 19:29:54 +02:00
Jonas Schnelli
cab0824c96
Logprint the start of a rescan 2018-04-09 18:49:09 +02:00
Wladimir J. van der Laan
a7cbe38ae2
Merge #12923: util: Pass pthread_self() to pthread_setschedparam instead of 0
b86730a util: Remove designator initializer from ScheduleBatchPriority (Wladimir J. van der Laan)
cff66e6 util: Pass pthread_self() to pthread_setschedparam instead of 0 (Wladimir J. van der Laan)

Pull request description:

  Nowhere in the man page of `pthread_setschedparam` it is mentioned that `0` is a valid value. The example uses `pthread_self()`, so should we.

  (noticed by Anthony Towns)
  Fixes #12915.

Tree-SHA512: 249e93b1ae7e3ba28de6ee6288400b91d21ca1b4ca41d82211f6c9609b62deb5ac87182c7bf08471d3a3e0c1af314c9ecd41f8ae864febe963b1de8a816dd82f
2018-04-09 17:33:10 +02:00
Wladimir J. van der Laan
b86730a4d7 util: Remove designator initializer from ScheduleBatchPriority
Although no compiler appears to complain about it, these are
not valid for c++11.
(http://en.cppreference.com/w/cpp/language/aggregate_initialization says they're c++20)

The structure is defined as:

   struct sched_param {
       int sched_priority;
   };

So passing 0 for the first field has the same effect.
2018-04-09 17:02:19 +02:00
Wladimir J. van der Laan
cff66e6a29 util: Pass pthread_self() to pthread_setschedparam instead of 0
Nowhere in the man page of `pthread_setschedparam` it is mentioned that
`0` is a valid value. The example uses `pthread_self()`, so should we.

(noticed by Anthony Towns)
2018-04-09 15:44:46 +02:00
MarcoFalke
fa385c3a8b
[doc] devtools: Setup ots git integration 2018-04-09 08:23:24 -04:00
MarcoFalke
603975b96a
Merge #12770: Use explicit casting in cuckoocache's compute_hashes(...) to clarify integer conversion
9142dfea81 Use explicit casting in cuckoocache's compute_hashes(...) to clarify integer conversion (practicalswift)

Pull request description:

  Use explicit casting in cuckoocache's `compute_hashes(...)` to clarify integer conversion.

  I discussed this code with the code's author @JeremyRubin who suggested patching it to avoid any confusion.

  At least one static analyzer incorrectly warns about a shift past bitwidth (UB) here, so this patch will help avoid confusion for human reviewers and static analyzers alike :-)

Tree-SHA512: 0419ee31b422d2ffedbd1a100688ec0ff5b0c1690d6d92592f638ca8db07a21a9650cb467923108c6f14a38d2bf07d6e6c85d2d1d4b7da53ffe6919f94f32655
2018-04-09 08:06:09 -04:00
MarcoFalke
cd8e45b4e7
Merge #12007: [Doc] Clarify the meaning of fee delta not being a fee rate in prioritisetransaction RPC
c198dc00e1 [Doc] Clarify the meaning of fee delta not being a fee rate in prioritisetransaction RPC (Jan Čapek)

Pull request description:

  Hi,

  I have faced some confusion among our developers considering this being a fee rate. Would you consider including this tiny doc update?

  Best regards,

  Jan Capek

Tree-SHA512: cd0560540418e53c5c19ceab2d5aca229f4ef6b788b9543695742522e1c63a7f2cce2574b47fead098a106da2f77e297f0c728474565f6259b50d62369bbe7da
2018-04-09 08:04:10 -04:00
MarcoFalke
a04440feb9
Merge #11878: Add Travis check for duplicate includes
c36b720d00 Add Travis check for duplicate includes (practicalswift)
280023f31d Remove duplicate includes (practicalswift)

Pull request description:

  This enforces parts of the project header include guidelines (added by @sipa in #10575).

  Example run:

  ```
  $ git diff
  diff --git a/src/warnings.cpp b/src/warnings.cpp
  index c52a1fd..d8994dd 100644
  --- a/src/warnings.cpp
  +++ b/src/warnings.cpp
  @@ -5,6 +5,8 @@

   #include <sync.h>
   #include <clientversion.h>
  +#include <string>
   #include <util.h>
   #include <warnings.h>
  +#include <util.h>

  diff --git a/src/warnings.h b/src/warnings.h
  index e8e982c..8d2252e 100644
  --- a/src/warnings.h
  +++ b/src/warnings.h
  @@ -7,6 +7,7 @@
   #define BITCOIN_WARNINGS_H

   #include <stdlib.h>
   #include <string>
  +#include <stdlib.h>

   void SetMiscWarning(const std::string& strWarning);
  $ contrib/devtools/lint-includes.sh
  Duplicate include(s) in src/warnings.h:
  #include <stdlib.h>

  Include(s) from src/warnings.h duplicated in src/warnings.cpp:
  #include <string>

  Duplicate include(s) in src/warnings.cpp:
  #include <util.h>
  $ echo $?
  1
  $ git checkout .
  $ contrib/devtools/lint-includes.sh
  $ echo $?
  0
  ```

Tree-SHA512: f653d23c58ebc024dfc5b1fb8570698fd3c515c75b60b5cabbc43595548c488fca92349fa4c8b64460edbe61c879ff1d24f37f959e18552e202a7342460ddbf1
2018-04-09 07:57:47 -04:00