diff --git a/.arclint b/.arclint index c098c39bda..e8519e77e3 100644 --- a/.arclint +++ b/.arclint @@ -1,158 +1,165 @@ { "linters": { "generated": { "type": "generated" }, "clang-format": { "type": "clang-format", "version": ">=7.0", "bin": ["clang-format-7", "clang-format"], "include": "(^src/.*\\.(h|c|cpp|mm)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "autopep8": { "type": "autopep8", "version": ">=1.3.4", "include": "(\\.py$)" }, "flake8": { "type": "flake8", "include": "(\\.py$)", "flags": [ "--select=E112,E113,E115,E116,E125,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,E901,E902,F401,F402,F403,F404,F405,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W292,W293,W601,W602,W603,W604,W605,W606" ] }, "lint-format-strings": { "type": "lint-format-strings", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "check-doc": { "type": "check-doc", "include": "(^src/.*\\.(h|c|cpp)$)" }, "lint-tests": { "type": "lint-tests", "include": "(^src/(rpc/|wallet/)?test/.*\\.(cpp)$)" }, "lint-python-format": { "type": "lint-python-format", "include": "(\\.py$)", "exclude": [ "(^test/lint/lint-python-format\\.py$)" ] }, "phpcs": { "type": "phpcs", "include": "(\\.php$)", "exclude": [ "(^arcanist/__phutil_library_.+\\.php$)" ], "phpcs.standard": "arcanist/phpcs.xml" }, "lint-locale-dependence": { "type": "lint-locale-dependence", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(crypto/ctaes/|leveldb/|secp256k1/|seeder/|tinyformat.h|univalue/))" ] }, "lint-cheader": { "type": "lint-cheader", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)" ] }, "spelling": { "type": "spelling", "exclude": [ "(^build-aux/m4/)", "(^depends/)", "(^doc/release-notes/)", "(^src/(qt/locale|secp256k1|univalue|leveldb)/)", "(^test/lint/dictionary/)" ], "spelling.dictionaries": [ "test/lint/dictionary/english.json" ] }, "lint-assert-with-side-effects": { "type": "lint-assert-with-side-effects", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-include-quotes": { "type": "lint-include-quotes", "include": "(^src/.*\\.(h|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-include-guard": { "type": "lint-include-guard", "include": "(^src/.*\\.h$)", "exclude": [ "(^src/(crypto/ctaes|secp256k1|univalue|leveldb)/)", "(^src/tinyformat.h$)" ] }, "lint-include-source": { "type": "lint-include-source", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-stdint": { "type": "lint-stdint", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-source-filename": { "type": "lint-source-filename", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "lint-boost-dependencies": { "type": "lint-boost-dependencies", "include": "(^src/.*\\.(h|cpp)$)" }, "check-rpc-mappings": { "type": "check-rpc-mappings", "include": "(^src/(rpc/|wallet/rpc).*\\.cpp$)" }, "lint-python-encoding": { "type": "lint-python-encoding", "include": "(\\.py$)" }, "lint-python-shebang": { "type": "lint-python-shebang", "include": "(\\.py$)", "exclude": [ "(__init__\\.py$)" ] }, "lint-bash-shebang": { "type": "lint-bash-shebang", "include": "(\\.sh$)" }, "shellcheck": { "type": "shellcheck", "include": "(\\.sh$)", "exclude": [ "(^src/(secp256k1|univalue)/)" ] + }, + "lint-shell-locale": { + "type": "lint-shell-locale", + "include": "(\\.sh$)", + "exclude": [ + "(^src/(secp256k1|univalue)/)" + ] } } } diff --git a/arcanist/.phutil_module_cache b/arcanist/.phutil_module_cache index 40f7e319ac..a0591c34a9 100644 --- a/arcanist/.phutil_module_cache +++ b/arcanist/.phutil_module_cache @@ -1 +1 @@ -{"__symbol_cache_version__":11,"ae5b7d3d6b8cf9598ce4abaf0cd56b21":{"have":{"class":{"ExtendedConfigurationDrivenLintEngine":19}},"need":{"function":{"newv":159,"pht":933},"class":{"ArcanistLintEngine":65,"ArcanistConfigurationDrivenLintEngine":171,"PhutilConsole":866},"class\/interface":{"ILintOnce":634}},"xmap":{"ExtendedConfigurationDrivenLintEngine":["ArcanistLintEngine"]}},"2809b09d2021203b43c57da33d1fe8bf":{"have":{"class":{"AssertWithSideEffectsLinter":210}},"need":{"function":{"pht":439},"class":{"ArcanistLinter":246,"ArcanistLintSeverity":926,"Filesystem":1170}},"xmap":{"AssertWithSideEffectsLinter":["ArcanistLinter"]}},"90a8b110dc475955f15bb81d37268cb5":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"execx":769,"id":1903},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1910,"Filesystem":1754,"ArcanistLinter":2017,"ArcanistLintSeverity":2095}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"4c4adcac26dddfa5e350b85a40097755":{"have":{"class":{"BashShebangLinter":82}},"need":{"function":{"pht":281},"class":{"ArcanistLinter":108,"ArcanistLintSeverity":597,"Filesystem":837}},"xmap":{"BashShebangLinter":["ArcanistLinter"]}},"5ea58c19df0397ed8ee0f463d90d6c72":{"have":{"class":{"BoostDependenciesLinter":145}},"need":{"function":{"pht":330,"id":1440},"class":{"GlobalExternalLinter":177,"ArcanistLintMessage":1447,"Filesystem":609,"ArcanistLinter":1524,"ArcanistLintSeverity":1624}},"xmap":{"BoostDependenciesLinter":["GlobalExternalLinter"]}},"38f0c676bff5192a344464142caaa253":{"have":{"class":{"CHeaderLinter":99}},"need":{"function":{"pht":611},"class":{"ArcanistLinter":121,"ArcanistLintSeverity":1060,"Filesystem":1307}},"xmap":{"CHeaderLinter":["ArcanistLinter"]}},"9bb48ec0fe2e9ced8e27d42540d0571c":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":321,"id":1845},"class":{"GlobalExternalLinter":129,"ArcanistLintMessage":1852,"Filesystem":729,"ArcanistLinter":1900,"ArcanistLintSeverity":1986}},"xmap":{"CheckDocLinter":["GlobalExternalLinter"]}},"63d19a8745cb2e1200cc26488dc7ad25":{"have":{"class":{"CheckRpcMappingsLinter":131}},"need":{"function":{"pht":310,"id":1386},"class":{"GlobalExternalLinter":162,"ArcanistLintMessage":1393,"Filesystem":573,"ArcanistLinter":1443,"ArcanistLintSeverity":1544}},"xmap":{"CheckRpcMappingsLinter":["GlobalExternalLinter"]}},"1c03a4631b02b8e1ebcc3a078dc1e4af":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":781,"id":2235},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":2242,"Filesystem":2086,"ArcanistLinter":2349,"ArcanistLintSeverity":2427}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"75579a609dd975aa0226add52700c622":{"have":{"class":{"FileNameLinter":103}},"need":{"function":{"pht":307},"class":{"ArcanistLinter":126,"ArcanistLintSeverity":662,"Filesystem":968}},"xmap":{"FileNameLinter":["ArcanistLinter"]}},"9285ad9415f8ebe564f7119e5a72c559":{"have":{"class":{"FormatStringLinter":146}},"need":{"function":{"pht":377,"csprintf":1492,"id":1872},"class":{"ArcanistExternalLinter":173,"ArcanistLintMessage":1879,"Filesystem":827,"ArcanistLinter":1956,"ArcanistLintSeverity":2044}},"xmap":{"FormatStringLinter":["ArcanistExternalLinter"]}},"2e11dd9ad67e594f863bc46ac59ea37e":{"have":{"class":{"GlobalExternalLinter":199}},"need":{"class":{"ArcanistExternalLinter":228},"interface":{"ILintOnce":262}},"xmap":{"GlobalExternalLinter":["ArcanistExternalLinter","ILintOnce"]}},"b2403124ec3e8be6cb4d10bf0f6c4134":{"have":{"interface":{"ILintOnce":69}},"need":[],"xmap":[]},"1f9bac7956f4f948a187828dcc6ba2d0":{"have":{"class":{"IncludeGuardLinter":98}},"need":{"function":{"pht":368},"class":{"ArcanistLinter":125,"ArcanistLintSeverity":721,"Filesystem":970}},"xmap":{"IncludeGuardLinter":["ArcanistLinter"]}},"2cbb6e7228d81557f777ad648704f343":{"have":{"class":{"IncludeQuotesLinter":100}},"need":{"function":{"pht":306},"class":{"ArcanistLinter":128,"ArcanistLintSeverity":663,"Filesystem":964}},"xmap":{"IncludeQuotesLinter":["ArcanistLinter"]}},"f151089cf79fdb8257b2272ed4782d88":{"have":{"class":{"IncludeSourceLinter":99}},"need":{"function":{"pht":391},"class":{"ArcanistLinter":127,"ArcanistLintSeverity":699,"Filesystem":938}},"xmap":{"IncludeSourceLinter":["ArcanistLinter"]}},"8a0f2ba683e96feeb9d9564af01fe3e7":{"have":{"class":{"LocaleDependenceLinter":160}},"need":{"function":{"pht":5460},"class":{"ArcanistLinter":191,"ArcanistLintSeverity":5963,"Filesystem":6209}},"xmap":{"LocaleDependenceLinter":["ArcanistLinter"]}},"6f2f22dd0f259fb2eaa284b4fab3bc29":{"have":{"class":{"PythonFormatLinter":123}},"need":{"function":{"pht":353,"id":1838},"class":{"ArcanistExternalLinter":150,"ArcanistLintMessage":1845,"Filesystem":776,"ArcanistLinter":1970,"ArcanistLintSeverity":2053}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}},"03cf226fe177a9fce7dc046816cc466b":{"have":{"class":{"PythonOpenFileEncodingLinter":111}},"need":{"function":{"pht":325},"class":{"ArcanistLinter":148,"ArcanistLintSeverity":687,"Filesystem":991}},"xmap":{"PythonOpenFileEncodingLinter":["ArcanistLinter"]}},"454160ed72e88797129d84ee589de304":{"have":{"class":{"PythonShebangLinter":87}},"need":{"function":{"pht":290},"class":{"ArcanistLinter":115,"ArcanistLintSeverity":614,"Filesystem":854}},"xmap":{"PythonShebangLinter":["ArcanistLinter"]}},"09a933fbbf135320585be52750d93831":{"have":{"class":{"StdintLinter":90}},"need":{"function":{"pht":280},"class":{"ArcanistLinter":111,"ArcanistLintSeverity":589,"Filesystem":897}},"xmap":{"StdintLinter":["ArcanistLinter"]}},"25781df78f6eebfb223296b8265e9d19":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2629},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2636,"Filesystem":776,"ArcanistLinter":2684,"ArcanistLintSeverity":2792}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"c5bb63c97d3e04f6e0906d001bd3f8a2":{"have":{"class":{"ShellCheckLinter":95}},"need":{"function":{"pht":921,"id":2137},"class":{"ArcanistExternalLinter":120,"ArcanistLintMessage":2144,"ArcanistLintSeverity":646,"ArcanistLinter":2192}},"xmap":{"ShellCheckLinter":["ArcanistExternalLinter"]}}} \ No newline at end of file +{"__symbol_cache_version__":11,"ae5b7d3d6b8cf9598ce4abaf0cd56b21":{"have":{"class":{"ExtendedConfigurationDrivenLintEngine":19}},"need":{"function":{"newv":159,"pht":933},"class":{"ArcanistLintEngine":65,"ArcanistConfigurationDrivenLintEngine":171,"PhutilConsole":866},"class\/interface":{"ILintOnce":634}},"xmap":{"ExtendedConfigurationDrivenLintEngine":["ArcanistLintEngine"]}},"2809b09d2021203b43c57da33d1fe8bf":{"have":{"class":{"AssertWithSideEffectsLinter":210}},"need":{"function":{"pht":439},"class":{"ArcanistLinter":246,"ArcanistLintSeverity":926,"Filesystem":1170}},"xmap":{"AssertWithSideEffectsLinter":["ArcanistLinter"]}},"90a8b110dc475955f15bb81d37268cb5":{"have":{"class":{"AutoPEP8FormatLinter":75}},"need":{"function":{"pht":297,"execx":769,"id":1903},"class":{"ArcanistExternalLinter":104,"ArcanistLintMessage":1910,"Filesystem":1754,"ArcanistLinter":2017,"ArcanistLintSeverity":2095}},"xmap":{"AutoPEP8FormatLinter":["ArcanistExternalLinter"]}},"4c4adcac26dddfa5e350b85a40097755":{"have":{"class":{"BashShebangLinter":82}},"need":{"function":{"pht":281},"class":{"ArcanistLinter":108,"ArcanistLintSeverity":597,"Filesystem":837}},"xmap":{"BashShebangLinter":["ArcanistLinter"]}},"5ea58c19df0397ed8ee0f463d90d6c72":{"have":{"class":{"BoostDependenciesLinter":145}},"need":{"function":{"pht":330,"id":1440},"class":{"GlobalExternalLinter":177,"ArcanistLintMessage":1447,"Filesystem":609,"ArcanistLinter":1524,"ArcanistLintSeverity":1624}},"xmap":{"BoostDependenciesLinter":["GlobalExternalLinter"]}},"38f0c676bff5192a344464142caaa253":{"have":{"class":{"CHeaderLinter":99}},"need":{"function":{"pht":611},"class":{"ArcanistLinter":121,"ArcanistLintSeverity":1060,"Filesystem":1307}},"xmap":{"CHeaderLinter":["ArcanistLinter"]}},"9bb48ec0fe2e9ced8e27d42540d0571c":{"have":{"class":{"CheckDocLinter":106}},"need":{"function":{"pht":321,"id":1845},"class":{"GlobalExternalLinter":129,"ArcanistLintMessage":1852,"Filesystem":729,"ArcanistLinter":1900,"ArcanistLintSeverity":1986}},"xmap":{"CheckDocLinter":["GlobalExternalLinter"]}},"63d19a8745cb2e1200cc26488dc7ad25":{"have":{"class":{"CheckRpcMappingsLinter":131}},"need":{"function":{"pht":310,"id":1386},"class":{"GlobalExternalLinter":162,"ArcanistLintMessage":1393,"Filesystem":573,"ArcanistLinter":1443,"ArcanistLintSeverity":1544}},"xmap":{"CheckRpcMappingsLinter":["GlobalExternalLinter"]}},"1c03a4631b02b8e1ebcc3a078dc1e4af":{"have":{"class":{"ClangFormatLinter":79}},"need":{"function":{"pht":302,"execx":781,"id":2235},"class":{"ArcanistExternalLinter":105,"ArcanistLintMessage":2242,"Filesystem":2086,"ArcanistLinter":2349,"ArcanistLintSeverity":2427}},"xmap":{"ClangFormatLinter":["ArcanistExternalLinter"]}},"75579a609dd975aa0226add52700c622":{"have":{"class":{"FileNameLinter":103}},"need":{"function":{"pht":307},"class":{"ArcanistLinter":126,"ArcanistLintSeverity":662,"Filesystem":968}},"xmap":{"FileNameLinter":["ArcanistLinter"]}},"9285ad9415f8ebe564f7119e5a72c559":{"have":{"class":{"FormatStringLinter":146}},"need":{"function":{"pht":377,"csprintf":1492,"id":1872},"class":{"ArcanistExternalLinter":173,"ArcanistLintMessage":1879,"Filesystem":827,"ArcanistLinter":1956,"ArcanistLintSeverity":2044}},"xmap":{"FormatStringLinter":["ArcanistExternalLinter"]}},"2e11dd9ad67e594f863bc46ac59ea37e":{"have":{"class":{"GlobalExternalLinter":199}},"need":{"class":{"ArcanistExternalLinter":228},"interface":{"ILintOnce":262}},"xmap":{"GlobalExternalLinter":["ArcanistExternalLinter","ILintOnce"]}},"b2403124ec3e8be6cb4d10bf0f6c4134":{"have":{"interface":{"ILintOnce":69}},"need":[],"xmap":[]},"1f9bac7956f4f948a187828dcc6ba2d0":{"have":{"class":{"IncludeGuardLinter":98}},"need":{"function":{"pht":368},"class":{"ArcanistLinter":125,"ArcanistLintSeverity":721,"Filesystem":970}},"xmap":{"IncludeGuardLinter":["ArcanistLinter"]}},"2cbb6e7228d81557f777ad648704f343":{"have":{"class":{"IncludeQuotesLinter":100}},"need":{"function":{"pht":306},"class":{"ArcanistLinter":128,"ArcanistLintSeverity":663,"Filesystem":964}},"xmap":{"IncludeQuotesLinter":["ArcanistLinter"]}},"f151089cf79fdb8257b2272ed4782d88":{"have":{"class":{"IncludeSourceLinter":99}},"need":{"function":{"pht":391},"class":{"ArcanistLinter":127,"ArcanistLintSeverity":699,"Filesystem":938}},"xmap":{"IncludeSourceLinter":["ArcanistLinter"]}},"8a0f2ba683e96feeb9d9564af01fe3e7":{"have":{"class":{"LocaleDependenceLinter":160}},"need":{"function":{"pht":5460},"class":{"ArcanistLinter":191,"ArcanistLintSeverity":5963,"Filesystem":6209}},"xmap":{"LocaleDependenceLinter":["ArcanistLinter"]}},"6f2f22dd0f259fb2eaa284b4fab3bc29":{"have":{"class":{"PythonFormatLinter":123}},"need":{"function":{"pht":353,"id":1838},"class":{"ArcanistExternalLinter":150,"ArcanistLintMessage":1845,"Filesystem":776,"ArcanistLinter":1970,"ArcanistLintSeverity":2053}},"xmap":{"PythonFormatLinter":["ArcanistExternalLinter"]}},"03cf226fe177a9fce7dc046816cc466b":{"have":{"class":{"PythonOpenFileEncodingLinter":111}},"need":{"function":{"pht":325},"class":{"ArcanistLinter":148,"ArcanistLintSeverity":687,"Filesystem":991}},"xmap":{"PythonOpenFileEncodingLinter":["ArcanistLinter"]}},"454160ed72e88797129d84ee589de304":{"have":{"class":{"PythonShebangLinter":87}},"need":{"function":{"pht":290},"class":{"ArcanistLinter":115,"ArcanistLintSeverity":614,"Filesystem":854}},"xmap":{"PythonShebangLinter":["ArcanistLinter"]}},"c5bb63c97d3e04f6e0906d001bd3f8a2":{"have":{"class":{"ShellCheckLinter":95}},"need":{"function":{"pht":921,"id":2137},"class":{"ArcanistExternalLinter":120,"ArcanistLintMessage":2144,"ArcanistLintSeverity":646,"ArcanistLinter":2192}},"xmap":{"ShellCheckLinter":["ArcanistExternalLinter"]}},"09a933fbbf135320585be52750d93831":{"have":{"class":{"StdintLinter":90}},"need":{"function":{"pht":280},"class":{"ArcanistLinter":111,"ArcanistLintSeverity":589,"Filesystem":897}},"xmap":{"StdintLinter":["ArcanistLinter"]}},"25781df78f6eebfb223296b8265e9d19":{"have":{"class":{"TestsLinter":103}},"need":{"function":{"pht":318,"id":2629},"class":{"ArcanistExternalLinter":123,"ArcanistLintMessage":2636,"Filesystem":776,"ArcanistLinter":2684,"ArcanistLintSeverity":2792}},"xmap":{"TestsLinter":["ArcanistExternalLinter"]}},"f0c1b22483ab7513a0e43189c6138f48":{"have":{"class":{"ShellLocaleLinter":80}},"need":{"function":{"pht":322},"class":{"ArcanistLinter":106,"ArcanistLintSeverity":641,"Filesystem":949}},"xmap":{"ShellLocaleLinter":["ArcanistLinter"]}}} \ No newline at end of file diff --git a/arcanist/__phutil_library_map__.php b/arcanist/__phutil_library_map__.php index cb005ed93a..7493035d45 100644 --- a/arcanist/__phutil_library_map__.php +++ b/arcanist/__phutil_library_map__.php @@ -1,64 +1,66 @@ 2, 'class' => array( 'AssertWithSideEffectsLinter' => 'linter/AssertWithSideEffectsLinter.php', 'AutoPEP8FormatLinter' => 'linter/AutoPEP8Linter.php', 'BashShebangLinter' => 'linter/BashShebangLinter.php', 'BoostDependenciesLinter' => 'linter/BoostDependenciesLinter.php', 'CHeaderLinter' => 'linter/CHeaderLinter.php', 'CheckDocLinter' => 'linter/CheckDocLinter.php', 'CheckRpcMappingsLinter' => 'linter/CheckRpcMappingsLinter.php', 'ClangFormatLinter' => 'linter/ClangFormatLinter.php', 'ExtendedConfigurationDrivenLintEngine' => 'engine/ExtendedConfigurationDrivenLintEngine.php', 'FileNameLinter' => 'linter/FileNameLinter.php', 'FormatStringLinter' => 'linter/FormatStringLinter.php', 'GlobalExternalLinter' => 'linter/GlobalExternalLinter.php', 'ILintOnce' => 'linter/ILintOnce.php', 'IncludeGuardLinter' => 'linter/IncludeGuardLinter.php', 'IncludeQuotesLinter' => 'linter/IncludeQuotesLinter.php', 'IncludeSourceLinter' => 'linter/IncludeSourceLinter.php', 'LocaleDependenceLinter' => 'linter/LocaleDependenceLinter.php', 'PythonFormatLinter' => 'linter/PythonFormatLinter.php', 'PythonOpenFileEncodingLinter' => 'linter/PythonOpenFileEncodingLinter.php', 'PythonShebangLinter' => 'linter/PythonShebangLinter.php', 'ShellCheckLinter' => 'linter/ShellCheckLinter.php', + 'ShellLocaleLinter' => 'linter/ShellLocaleLinter.php', 'StdintLinter' => 'linter/StdintLinter.php', 'TestsLinter' => 'linter/TestsLinter.php', ), 'function' => array(), 'xmap' => array( 'AssertWithSideEffectsLinter' => 'ArcanistLinter', 'AutoPEP8FormatLinter' => 'ArcanistExternalLinter', 'BashShebangLinter' => 'ArcanistLinter', 'BoostDependenciesLinter' => 'GlobalExternalLinter', 'CHeaderLinter' => 'ArcanistLinter', 'CheckDocLinter' => 'GlobalExternalLinter', 'CheckRpcMappingsLinter' => 'GlobalExternalLinter', 'ClangFormatLinter' => 'ArcanistExternalLinter', 'ExtendedConfigurationDrivenLintEngine' => 'ArcanistLintEngine', 'FileNameLinter' => 'ArcanistLinter', 'FormatStringLinter' => 'ArcanistExternalLinter', 'GlobalExternalLinter' => array( 'ArcanistExternalLinter', 'ILintOnce', ), 'IncludeGuardLinter' => 'ArcanistLinter', 'IncludeQuotesLinter' => 'ArcanistLinter', 'IncludeSourceLinter' => 'ArcanistLinter', 'LocaleDependenceLinter' => 'ArcanistLinter', 'PythonFormatLinter' => 'ArcanistExternalLinter', 'PythonOpenFileEncodingLinter' => 'ArcanistLinter', 'PythonShebangLinter' => 'ArcanistLinter', 'ShellCheckLinter' => 'ArcanistExternalLinter', + 'ShellLocaleLinter' => 'ArcanistLinter', 'StdintLinter' => 'ArcanistLinter', 'TestsLinter' => 'ArcanistExternalLinter', ), )); diff --git a/arcanist/linter/ShellLocaleLinter.php b/arcanist/linter/ShellLocaleLinter.php new file mode 100644 index 0000000000..c8170c2f31 --- /dev/null +++ b/arcanist/linter/ShellLocaleLinter.php @@ -0,0 +1,56 @@ + ArcanistLintSeverity::SEVERITY_ERROR, + ); + } + + public function getLintNameMap() { + return array( + self::INVALID_LOCALE => pht('`'.self::LOCALE_STATEMENT.'` should be '. + 'the first statement.'), + ); + } + + public function lintPath($path) { + $absPath = Filesystem::resolvePath($path, $this->getProjectRoot()); + $fileContent = Filesystem::readFile($absPath); + + if (!preg_match_all('/^[^#\s]+.+/m', $fileContent, $matches)) { + throw new Exception(pht('Error while parsing %s: the script seems to '. + 'have only comments and/or empty lines.', $path)); + } + + if (!(trim($matches[0][0]) === self::LOCALE_STATEMENT)) { + return $this->raiseLintAtPath( + self::INVALID_LOCALE, + pht('Shell scripts should set the locale to avoid side effects.') + ); + } + } +} diff --git a/autogen.sh b/autogen.sh index f567e42327..2c434e9ef0 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,15 +1,16 @@ #!/bin/sh # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C set -e srcdir="$(dirname $0)" cd "$srcdir" if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="$(command -v glibtoolize)"; then LIBTOOLIZE="${GLIBTOOLIZE}" export LIBTOOLIZE fi command -v autoreconf >/dev/null || \ (echo "configuration failed, please install autoconf first" && exit 1) autoreconf --install --force --warnings=all diff --git a/contrib/devtools/gen-manpages.sh b/contrib/devtools/gen-manpages.sh index 03c065a7b7..c583c44223 100755 --- a/contrib/devtools/gen-manpages.sh +++ b/contrib/devtools/gen-manpages.sh @@ -1,31 +1,32 @@ #!/usr/bin/env bash +export LC_ALL=C TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} BUILDDIR=${BUILDDIR:-$TOPDIR} BINDIR=${BINDIR:-$BUILDDIR/src} MANDIR=${MANDIR:-$TOPDIR/doc/man} BITCOIND=${BITCOIND:-$BINDIR/bitcoind} BITCOINCLI=${BITCOINCLI:-$BINDIR/bitcoin-cli} BITCOINTX=${BITCOINTX:-$BINDIR/bitcoin-tx} BITCOINQT=${BITCOINQT:-$BINDIR/qt/bitcoin-qt} [ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1 # The autodetected version git tag can screw up manpage output a little bit read -r -a BTCVER <<< "$($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ print $6, $7 }')" # Create a footer file with copyright content. # This gets autodetected fine for bitcoind if --version-string is not set, # but has different outcomes for bitcoin-qt and bitcoin-cli. echo "[COPYRIGHT]" > footer.h2m $BITCOIND --version | sed -n '1!p' >> footer.h2m for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $BITCOINQT; do cmdname="${cmd##*/}" help2man -N --version-string=${BTCVER[0]} --include=footer.h2m -o ${MANDIR}/${cmdname}.1 ${cmd} sed -i "s/\\\-${BTCVER[1]}//g" ${MANDIR}/${cmdname}.1 done rm -f footer.h2m diff --git a/contrib/gitian-signing/check-keys.sh b/contrib/gitian-signing/check-keys.sh index a6ad1d08f6..951477ea60 100755 --- a/contrib/gitian-signing/check-keys.sh +++ b/contrib/gitian-signing/check-keys.sh @@ -1,6 +1,9 @@ #!/usr/bin/env bash + +export LC_ALL=C + # Fetch latest signers' keys. We do this in order to check if a key was revoked. while read fingerprint _ do gpg --recv-keys ${fingerprint} done < ./keys.txt diff --git a/contrib/gitian/provisioner.sh b/contrib/gitian/provisioner.sh index 9e2e026b71..0d44ab68c2 100644 --- a/contrib/gitian/provisioner.sh +++ b/contrib/gitian/provisioner.sh @@ -1,66 +1,68 @@ #!/usr/bin/env bash +export LC_ALL=C + set -e # User to setup for building. Vagrant is the default export BUILDUSER=${BUILDUSER:-vagrant} apt-get update apt-get install -y git ruby sudo apt-cacher-ng qemu-utils debootstrap \ lxc python-cheetah parted kpartx bridge-utils make curl # the version of lxc-start in Debian needs to run as root, so make sure # that the build script can execute it without providing a password echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-start" > /etc/sudoers.d/gitian-lxc echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-execute" >> /etc/sudoers.d/gitian-lxc # make sure that USE_LXC is always set when logging in as vagrant, # and configure LXC IP addresses { echo 'export USE_LXC=1' echo 'export LXC_BRIDGE=lxcbr0' echo 'export GITIAN_HOST_IP=10.0.3.1' echo 'export LXC_GUEST_IP=10.0.3.5' } >> /home/${BUILDUSER}/.profile # Setup bridge echo 'USE_LXC_BRIDGE="true"' > /etc/default/lxc-net { echo 'lxc.network.type = veth' echo 'lxc.network.link = lxcbr0' echo 'lxc.network.flags = up' echo 'lxc.network.hwaddr = 00:16:3e:xx:xx:xx' } > /etc/lxc/default.conf service lxc-net restart # chdir into build user home directory cd /home/${BUILDUSER}/ ## Install vm-builder wget http://archive.ubuntu.com/ubuntu/pool/universe/v/vm-builder/vm-builder_0.12.4+bzr494.orig.tar.gz echo "76cbf8c52c391160b2641e7120dbade5afded713afaa6032f733a261f13e6a8e vm-builder_0.12.4+bzr494.orig.tar.gz" | sha256sum -c # (verification -- must return OK) tar -zxvf vm-builder_0.12.4+bzr494.orig.tar.gz cd vm-builder-0.12.4+bzr494 sudo python setup.py install cd .. ## Install Gitian git clone https://github.com/devrandom/gitian-builder.git cd gitian-builder git config --global user.email "vagrant@vagrant.com" git config --global user.name "vagrant" chown -R ${BUILDUSER}:${BUILDUSER} /home/${BUILDUSER} echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "!!! Provisioning Complete !!!!" echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo echo "As the user ${BUILDUSER} run the following commands to produce a linux build:" echo "export COMMIT=v0.18.3" echo "export URL=https://github.com/Bitcoin-ABC/bitcoin-abc.git" echo "cd gitian-builder" echo "./bin/make-base-vm --lxc --distro debian --suite stretch --arch amd64" echo "./bin/gbuild --commit bitcoin=\${COMMIT} --url bitcoin=\${URL} /vagrant/contrib/gitian-descriptors/gitian-linux.yml" diff --git a/contrib/macdeploy/detached-sig-apply.sh b/contrib/macdeploy/detached-sig-apply.sh index 7fe15e793b..af2b11fa0d 100755 --- a/contrib/macdeploy/detached-sig-apply.sh +++ b/contrib/macdeploy/detached-sig-apply.sh @@ -1,56 +1,57 @@ #!/bin/sh # Copyright (c) 2014-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C set -e UNSIGNED="$1" SIGNATURE="$2" ARCH=x86_64 ROOTDIR=dist TEMPDIR=signed.temp OUTDIR=signed-app if [ -z "$UNSIGNED" ]; then echo "usage: $0 " exit 1 fi if [ -z "$SIGNATURE" ]; then echo "usage: $0 " exit 1 fi rm -rf ${TEMPDIR} && mkdir -p ${TEMPDIR} tar -C ${TEMPDIR} -xf ${UNSIGNED} cp -rf "${SIGNATURE}"/* ${TEMPDIR} if [ -z "${PAGESTUFF}" ]; then PAGESTUFF=${TEMPDIR}/pagestuff fi if [ -z "${CODESIGN_ALLOCATE}" ]; then CODESIGN_ALLOCATE=${TEMPDIR}/codesign_allocate fi find ${TEMPDIR} -name "*.sign" | while read i; do SIZE=$(stat -c %s "${i}") TARGET_FILE="$(echo "${i}" | sed 's/\.sign$//')" echo "Allocating space for the signature of size ${SIZE} in ${TARGET_FILE}" ${CODESIGN_ALLOCATE} -i "${TARGET_FILE}" -a ${ARCH} ${SIZE} -o "${i}.tmp" OFFSET=$(${PAGESTUFF} "${i}.tmp" -p | tail -2 | grep offset | sed 's/[^0-9]*//g') if [ -z ${QUIET} ]; then echo "Attaching signature at offset ${OFFSET}" fi dd if="$i" of="${i}.tmp" bs=1 seek=${OFFSET} count=${SIZE} 2>/dev/null mv "${i}.tmp" "${TARGET_FILE}" rm "${i}" echo "Success." done mv ${TEMPDIR}/${ROOTDIR} ${OUTDIR} rm -rf ${TEMPDIR} echo "Signed: ${OUTDIR}" diff --git a/contrib/macdeploy/detached-sig-create.sh b/contrib/macdeploy/detached-sig-create.sh index efa4d14bca..9e9c06b84a 100755 --- a/contrib/macdeploy/detached-sig-create.sh +++ b/contrib/macdeploy/detached-sig-create.sh @@ -1,51 +1,52 @@ #!/bin/sh # Copyright (c) 2014-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C set -e ROOTDIR=dist BUNDLE="${ROOTDIR}/BitcoinABC-Qt.app" CODESIGN=codesign TEMPDIR=sign.temp TEMPLIST=${TEMPDIR}/signatures.txt OUT=signature.tar.gz OUTROOT=osx if [ -z "$1" ]; then echo "usage: $0 " echo "example: $0 -s MyIdentity" exit 1 fi rm -rf ${TEMPDIR} ${TEMPLIST} mkdir -p ${TEMPDIR} ${CODESIGN} -f --file-list ${TEMPLIST} "$@" "${BUNDLE}" grep -v CodeResources < "${TEMPLIST}" | while read i; do TARGETFILE="${BUNDLE}/$(echo "${i}" | sed "s|.*${BUNDLE}/||")" SIZE=$(pagestuff "$i" -p | tail -2 | grep size | sed 's/[^0-9]*//g') OFFSET=$(pagestuff "$i" -p | tail -2 | grep offset | sed 's/[^0-9]*//g') SIGNFILE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}.sign" DIRNAME="$(dirname "${SIGNFILE}")" mkdir -p "${DIRNAME}" echo "Adding detached signature for: ${TARGETFILE}. Size: ${SIZE}. Offset: ${OFFSET}" dd if="$i" of="${SIGNFILE}" bs=1 skip=${OFFSET} count=${SIZE} 2>/dev/null done grep CodeResources < "${TEMPLIST}" | while read i; do TARGETFILE="${BUNDLE}/$(echo "${i}" | sed "s|.*${BUNDLE}/||")" RESOURCE="${TEMPDIR}/${OUTROOT}/${TARGETFILE}" DIRNAME="$(dirname "${RESOURCE}")" mkdir -p "${DIRNAME}" echo "Adding resource for: \"${TARGETFILE}\"" cp "${i}" "${RESOURCE}" done rm ${TEMPLIST} tar -C "${TEMPDIR}" -czf "${OUT}" . rm -rf "${TEMPDIR}" echo "Created ${OUT}" diff --git a/contrib/macdeploy/extract-osx-sdk.sh b/contrib/macdeploy/extract-osx-sdk.sh index 956cd2aa35..4c175156f4 100755 --- a/contrib/macdeploy/extract-osx-sdk.sh +++ b/contrib/macdeploy/extract-osx-sdk.sh @@ -1,33 +1,34 @@ #!/usr/bin/env bash # Copyright (c) 2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C set -e INPUTFILE="Xcode_7.3.1.dmg" HFSFILENAME="5.hfs" SDKDIR="Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk" 7z x "${INPUTFILE}" "${HFSFILENAME}" SDKNAME="$(basename "${SDKDIR}")" SDKDIRINODE=$(ifind -n "${SDKDIR}" "${HFSFILENAME}") fls "${HFSFILENAME}" -rpF ${SDKDIRINODE} | while read type inode filename; do inode="${inode::-1}" if [ "${filename:0:14}" = "usr/share/man/" ]; then continue fi filename="${SDKNAME}/$filename" echo "Extracting $filename ..." mkdir -p "$(dirname "$filename")" if [ "$type" = "l/l" ]; then ln -s "$(icat "${HFSFILENAME}" $inode)" "$filename" else icat "${HFSFILENAME}" $inode >"$filename" fi done echo "Building ${SDKNAME}.tar.gz ..." MTIME="$(istat "${HFSFILENAME}" "${SDKDIRINODE}" | perl -nle 'm/Content Modified:\s+(.*?)\s\(/ && print $1')" find "${SDKNAME}" | sort | tar --no-recursion --mtime="${MTIME}" --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > "${SDKNAME}.tar.gz" echo 'All done!' diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh index 3a346d99a4..ccb0f4f895 100644 --- a/contrib/qos/tc.sh +++ b/contrib/qos/tc.sh @@ -1,61 +1,62 @@ #!/usr/bin/env bash # # Copyright (c) 2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C #network interface on which to limit traffic IF="eth0" #limit of the network interface in question LINKCEIL="1gbit" #limit outbound Bitcoin protocol traffic to this rate LIMIT="160kbit" #defines the IPv4 address space for which you wish to disable rate limiting LOCALNET_V4="192.168.0.0/16" #defines the IPv6 address space for which you wish to disable rate limiting LOCALNET_V6="fe80::/10" #delete existing rules tc qdisc del dev ${IF} root #add root class tc qdisc add dev ${IF} root handle 1: htb default 10 #add parent class tc class add dev ${IF} parent 1: classid 1:1 htb rate ${LINKCEIL} ceil ${LINKCEIL} #add our two classes. one unlimited, another limited tc class add dev ${IF} parent 1:1 classid 1:10 htb rate ${LINKCEIL} ceil ${LINKCEIL} prio 0 tc class add dev ${IF} parent 1:1 classid 1:11 htb rate ${LIMIT} ceil ${LIMIT} prio 1 #add handles to our classes so packets marked with go into the class with "... handle fw ..." tc filter add dev ${IF} parent 1: protocol ip prio 1 handle 1 fw classid 1:10 tc filter add dev ${IF} parent 1: protocol ip prio 2 handle 2 fw classid 1:11 if [ -n "${LOCALNET_V6}" ] ; then # v6 cannot have the same priority value as v4 tc filter add dev ${IF} parent 1: protocol ipv6 prio 3 handle 1 fw classid 1:10 tc filter add dev ${IF} parent 1: protocol ipv6 prio 4 handle 2 fw classid 1:11 fi #delete any existing rules #disable for now #ret=0 #while [ $ret -eq 0 ]; do # iptables -t mangle -D OUTPUT 1 # ret=$? #done #limit outgoing traffic to and from port 8333. but not when dealing with a host on the local network # (defined by $LOCALNET_V4 and $LOCALNET_V6) # --set-mark marks packages matching these criteria with the number "2" (v4) # --set-mark marks packages matching these criteria with the number "4" (v6) # these packets are filtered by the tc filter with "handle 2" # this filter sends the packages into the 1:11 class, and this class is limited to ${LIMIT} iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2 iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V4} -j MARK --set-mark 0x2 if [ -n "${LOCALNET_V6}" ] ; then ip6tables -t mangle -A OUTPUT -p tcp -m tcp --dport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 ip6tables -t mangle -A OUTPUT -p tcp -m tcp --sport 8333 ! -d ${LOCALNET_V6} -j MARK --set-mark 0x4 fi diff --git a/contrib/teamcity/build-configurations.sh b/contrib/teamcity/build-configurations.sh index 4a5f0d85ed..f32883028a 100755 --- a/contrib/teamcity/build-configurations.sh +++ b/contrib/teamcity/build-configurations.sh @@ -1,40 +1,42 @@ #!/usr/bin/env bash +export LC_ALL=C + set -e if [ -z "$ABC_BUILD_NAME" ]; then echo "Error: Environment variable ABC_BUILD_NAME must be set" exit 1 fi echo "Running build configuration '${ABC_BUILD_NAME}'..." TOPLEVEL=$(git rev-parse --show-toplevel) cd "${TOPLEVEL}/contrib/teamcity" case "$ABC_BUILD_NAME" in build-asan) export CONFIGURE_FLAGS="--enable-debug --with-sanitizers=address --disable-ccache" ./build.sh ;; build-ubsan) export CONFIGURE_FLAGS="--enable-debug --with-sanitizers=undefined --disable-ccache CC=clang CXX=clang++" ./build.sh ;; build-default) ./build.sh ./build-secp256k1.sh ;; build-without-wallet) export DISABLE_WALLET=1 ./build.sh ;; *) echo "Error: Invalid build name '${ABC_BUILD_NAME}'" exit 2 ;; esac diff --git a/contrib/teamcity/build-secp256k1.sh b/contrib/teamcity/build-secp256k1.sh index 228c832ee7..fd3369af5c 100755 --- a/contrib/teamcity/build-secp256k1.sh +++ b/contrib/teamcity/build-secp256k1.sh @@ -1,30 +1,32 @@ #!/usr/bin/env bash +export LC_ALL=C + set -eu TOPLEVEL=$(git rev-parse --show-toplevel) if [[ -z "${TOPLEVEL}" ]]; then echo "No .git directory found, assuming pwd" TOPLEVEL=$(pwd -P) fi SECP_DIR="${TOPLEVEL}/src/secp256k1" # Generate necessary autoconf files cd ${SECP_DIR} ./autogen.sh # Setup build directory BUILD_DIR="${SECP_DIR}/build" mkdir -p ${BUILD_DIR} cd ${BUILD_DIR} # Determine the number of build threads THREADS=$(nproc || sysctl -n hw.ncpu) ../configure --enable-jni --enable-experimental --enable-module-ecdh # Run build make -j ${THREADS} # Run Java tests make check-java diff --git a/contrib/teamcity/build.sh b/contrib/teamcity/build.sh index d5b016425e..e77fc9d783 100755 --- a/contrib/teamcity/build.sh +++ b/contrib/teamcity/build.sh @@ -1,88 +1,90 @@ #!/usr/bin/env bash +export LC_ALL=C + set -eu TOPLEVEL=$(git rev-parse --show-toplevel) if [[ -z "${TOPLEVEL}" ]]; then echo "No .git directory found, assuming pwd" TOPLEVEL=$(pwd -P) fi BUILD_DIR="${TOPLEVEL}/build" mkdir -p ${BUILD_DIR} ## Generate necessary autoconf files cd ${TOPLEVEL} ./autogen.sh cd ${BUILD_DIR} rm -f build.status test_bitcoin.xml ## Determine the number of build threads THREADS=$(nproc || sysctl -n hw.ncpu) # Default to nothing : "${DISABLE_WALLET:=}" : "${CONFIGURE_FLAGS:=}" read -a CONFIGURE_FLAGS <<< "$CONFIGURE_FLAGS --prefix=$(pwd)" if [[ -n "${DISABLE_WALLET}" ]]; then echo "*** Building without wallet" CONFIGURE_FLAGS+=("--disable-wallet") fi ../configure "${CONFIGURE_FLAGS[@]}" # Base directories for sanitizer related files SAN_SUPP_DIR="${TOPLEVEL}/test/sanitizer_suppressions" SAN_LOG_DIR="${BUILD_DIR}/sanitizer_logs" # Create the log directory if it doesn't exist and clear it mkdir -p "${SAN_LOG_DIR}" rm -rf "${SAN_LOG_DIR:?}"/* # Sanitizers options, not used if sanitizers are not enabled export ASAN_OPTIONS="malloc_context_size=0:log_path=${SAN_LOG_DIR}/asan.log" export LSAN_OPTIONS="suppressions=${SAN_SUPP_DIR}/lsan:log_path=${SAN_LOG_DIR}/lsan.log" export TSAN_OPTIONS="suppressions=${SAN_SUPP_DIR}/tsan:log_path=${SAN_LOG_DIR}/tsan.log" export UBSAN_OPTIONS="suppressions=${SAN_SUPP_DIR}/ubsan:print_stacktrace=1:halt_on_error=1:log_path=${SAN_LOG_DIR}/ubsan.log" function print_sanitizers_log() { for log in "${SAN_LOG_DIR}"/*.log.* do echo "*** Output of ${log} ***" cat "${log}" done } # Run build make -j ${THREADS} # Default to nothing : "${DISABLE_TESTS:=}" # If DISABLE_TESTS is unset (default), run the tests if [[ -z "${DISABLE_TESTS}" ]]; then echo "*** Running tests" # Run unit tests make -j ${THREADS} check || (print_sanitizers_log && exit 1) mkdir -p output/ BRANCH=$(git rev-parse --abbrev-ref HEAD) JUNIT_DEFAULT="junit_results_default.xml" JUNIT_NEXT_UPGRADE="junit_results_next_upgrade.xml" if [[ -n "${DISABLE_WALLET}" ]]; then echo "Skipping rpc testing due to disabled wallet functionality." elif [[ "${BRANCH}" == "master" ]]; then ./test/functional/test_runner.py -J="${JUNIT_DEFAULT}" --cutoff=600 --tmpdirprefix=output ./test/functional/test_runner.py -J="${JUNIT_NEXT_UPGRADE}" --cutoff=600 --tmpdirprefix=output --with-gravitonactivation else ./test/functional/test_runner.py -J="${JUNIT_DEFAULT}" --tmpdirprefix=output ./test/functional/test_runner.py -J="${JUNIT_NEXT_UPGRADE}" --tmpdirprefix=output --with-gravitonactivation fi else echo "*** Tests have been skipped" fi diff --git a/contrib/teamcity/gitian.sh b/contrib/teamcity/gitian.sh index b3a0f43725..dd8f911a51 100755 --- a/contrib/teamcity/gitian.sh +++ b/contrib/teamcity/gitian.sh @@ -1,35 +1,37 @@ #!/usr/bin/env bash +export LC_ALL=C + set -e cd "$(dirname "$0")" COMMIT=$(git rev-parse HEAD) export COMMIT PROJECT_ROOT=$(git rev-parse --show-toplevel) export PROJECT_ROOT export USE_LXC=1 export GITIAN_HOST_IP=10.0.3.1 export LXC_BRIDGE=lxcbr0 export LXC_GUEST_IP=10.0.3.5 cd ~/gitian-builder if [[ "${OS_NAME}" == "osx" ]]; then wget https://storage.googleapis.com/f4936e83b2dcbca742be51fb9692b153/MacOSX10.11.sdk.tar.gz echo "4732b52b5ebe300c8c91cbeed6d19d59c1ff9c56c7a1dd6cfa518b9c2c72abde MacOSX10.11.sdk.tar.gz" | sha256sum -c mkdir -p inputs echo "Downloaded" mv MacOSX10.11.sdk.tar.gz inputs fi ## Determine the number of build threads THREADS=$(nproc || sysctl -n hw.ncpu) ./bin/gbuild -j${THREADS} -m3500 --commit bitcoin=${COMMIT} --url bitcoin="${PROJECT_ROOT}" "${PROJECT_ROOT}/contrib/gitian-descriptors/gitian-${OS_NAME}.yml" RESULT_DIR="${PROJECT_ROOT}/gitian-results/${OS_NAME}" mkdir -p "${RESULT_DIR}" mv var/build.log "${PROJECT_ROOT}/gitian-results/" mv result/*.yml "${RESULT_DIR}/" mv build/out/* "${RESULT_DIR}/" diff --git a/contrib/teamcity/ibd.sh b/contrib/teamcity/ibd.sh index ad933b23c1..15c9ae64b3 100755 --- a/contrib/teamcity/ibd.sh +++ b/contrib/teamcity/ibd.sh @@ -1,74 +1,76 @@ #!/usr/bin/env bash +export LC_ALL=C + set -euo pipefail ### # Initial Block Download script. # # Runs a bitcoind process until initial block download is complete. # Forwards the exit code from bitcoind onward. ### MYPID=$$ # Setup DATA_DIR="ibd" mkdir -p "${DATA_DIR}" DEBUG_LOG="${DATA_DIR}/debug.log" touch "${DEBUG_LOG}" chmod +x bitcoind # Launch bitcoind using this script's parameters ./bitcoind "-datadir=${DATA_DIR}" "$@" & BITCOIND_PID=$! cleanup() { # Cleanup background processes spawned by this script. pkill -P ${MYPID} tail || true } trap "cleanup" EXIT # Show some progress tail -f "${DEBUG_LOG}" | grep 'UpdateTip' | awk 'NR % 10000 == 0' & # Wait for IBD to finish and kill the daemon ( ( # Ignore the broken pipe when tail tries to write pipe closed by grep set +o pipefail tail -f "${DEBUG_LOG}" | grep -m 1 'progress=1.000000' ) echo "Initial block download complete." # TODO Add more checks to see if IBD completed as expected, # These checks will exit the subshell with a non-zero exit code. ) & IBD_PID=$! # When the IBD subshell finishes, kill bitcoind ( while [ -e /proc/${IBD_PID} ]; do sleep 0.1; done echo "Cleaning up bitcoin daemon (PID: ${BITCOIND_PID})." kill ${BITCOIND_PID} ) & # Wait for bitcoind to exit, whether it exited on its own or IBD finished wait ${BITCOIND_PID} BITCOIND_EXIT_CODE=$? if [ "${BITCOIND_EXIT_CODE}" -ne "0" ]; then echo "bitcoind exited unexpectedly with code: ${BITCOIND_EXIT_CODE}" exit ${BITCOIND_EXIT_CODE} fi # Get the exit code for the IBD subshell, which should have exited already wait ${IBD_PID} IBD_EXIT_CODE=$? # The IBD subshell should only exit with a non-zero code if one of the tests # failed. if [ "${IBD_EXIT_CODE}" -ne "0" ]; then echo "IBD tests failed with code: ${IBD_EXIT_CODE}" exit ${IBD_EXIT_CODE} fi diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index 8071eb87e0..a56cdf00b6 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -1,124 +1,125 @@ #!/usr/bin/env bash # Copyright (c) 2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. ### This script attempts to download the signature file SHA256SUMS.asc from bitcoin.org ### It first checks if the signature passes, and then downloads the files specified in ### the file, and checks if the hashes of these files match those that are specified ### in the signature file. ### The script returns 0 if everything passes the checks. It returns 1 if either the ### signature check or the hash check doesn't pass. If an error occurs the return value is 2 +export LC_ALL=C function clean_up { for file in "$@" do rm "$file" 2> /dev/null done } WORKINGDIR="/tmp/bitcoin_verify_binaries" TMPFILE="hashes.tmp" SIGNATUREFILENAME="SHA256SUMS.asc" RCSUBDIR="test" BASEDIR="https://bitcoin.org/bin/" VERSIONPREFIX="bitcoin-core-" RCVERSIONSTRING="rc" if [ ! -d "$WORKINGDIR" ]; then mkdir "$WORKINGDIR" fi cd "$WORKINGDIR" || exit 1 #test if a version number has been passed as an argument if [ -n "$1" ]; then #let's also check if the version number includes the prefix 'bitcoin-', # and add this prefix if it doesn't if [[ $1 == "$VERSIONPREFIX"* ]]; then VERSION="$1" else VERSION="$VERSIONPREFIX$1" fi #now let's see if the version string contains "rc", and strip it off if it does # and simultaneously add RCSUBDIR to BASEDIR, where we will look for SIGNATUREFILENAME if [[ $VERSION == *"$RCVERSIONSTRING"* ]]; then BASEDIR="$BASEDIR${VERSION/%-$RCVERSIONSTRING*}/" BASEDIR="$BASEDIR$RCSUBDIR.$RCVERSIONSTRING${VERSION: -1}/" else BASEDIR="$BASEDIR$VERSION/" fi else echo "Error: need to specify a version on the command line" exit 2 fi if ! WGETOUT=$(wget -N "$HOST1$BASEDIR$SIGNATUREFILENAME" 2>&1); then echo "Error: couldn't fetch signature file. Have you specified the version number in the following format?" # shellcheck disable=SC1087 echo "[$VERSIONPREFIX]-[$RCVERSIONSTRING[0-9]] (example: ${VERSIONPREFIX}0.10.4-${RCVERSIONSTRING}1)" echo "wget output:" # shellcheck disable=SC2001 echo "$WGETOUT"|sed 's/^/\t/g' exit 2 fi #then we check it GPGOUT=$(gpg --yes --decrypt --output "$TMPFILE" "$SIGNATUREFILENAME" 2>&1) #return value 0: good signature #return value 1: bad signature #return value 2: gpg error RET="$?" if [ $RET -ne 0 ]; then if [ $RET -eq 1 ]; then #and notify the user if it's bad echo "Bad signature." elif [ $RET -eq 2 ]; then #or if a gpg error has occurred echo "gpg error. Do you have the Bitcoin Core binary release signing key installed?" fi echo "gpg output:" # shellcheck disable=SC2001 echo "$GPGOUT"|sed 's/^/\t/g' clean_up $SIGNATUREFILENAME $TMPFILE exit "$RET" fi #here we extract the filenames from the signature file FILES=$(awk '{print $2}' "$TMPFILE") #and download these one by one for file in $FILES do wget --quiet -N "$BASEDIR$file" done #check hashes DIFF=$(diff <(sha256sum $FILES) "$TMPFILE") if [ $? -eq 1 ]; then echo "Hashes don't match." echo "Offending files:" echo "$DIFF"|grep "^<"|awk '{print "\t"$3}' exit 1 elif [ $? -gt 1 ]; then echo "Error executing 'diff'" exit 2 fi if [ -n "$2" ]; then echo "Clean up the binaries" clean_up $FILES $SIGNATUREFILENAME $TMPFILE else echo "Keep the binaries in $WORKINGDIR" clean_up $TMPFILE fi echo -e "Verified hashes of \n$FILES" exit 0 diff --git a/share/genbuild.sh b/share/genbuild.sh index b21a734d41..208f7fc932 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -1,48 +1,49 @@ #!/bin/sh # Copyright (c) 2012-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C if [ $# -gt 1 ]; then cd "$2" || exit 1 fi if [ $# -gt 0 ]; then FILE="$1" shift if [ -f "$FILE" ]; then INFO="$(head -n 1 "$FILE")" fi else echo "Usage: $0 " exit 1 fi DESC="" SUFFIX="" if [ -e "$(command -v git)" ] && [ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then # clean 'dirty' status of touched files that haven't been modified git diff >/dev/null 2>/dev/null # if latest commit is tagged and not dirty, then override using the tag name RAWDESC=$(git describe --abbrev=0 2>/dev/null) if [ "$(git rev-parse HEAD)" = "$(git rev-list -1 $RAWDESC 2>/dev/null)" ]; then git diff-index --quiet HEAD -- && DESC=$RAWDESC fi # otherwise generate suffix from git, i.e. string like "59887e8-dirty" SUFFIX=$(git rev-parse --short HEAD) git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty" fi if [ -n "$DESC" ]; then NEWINFO="#define BUILD_DESC \"$DESC\"" elif [ -n "$SUFFIX" ]; then NEWINFO="#define BUILD_SUFFIX $SUFFIX" else NEWINFO="// No build information available" fi # only update build.h if necessary if [ "$INFO" != "$NEWINFO" ]; then echo "$NEWINFO" >"$FILE" fi diff --git a/src/qt/res/movies/makespinner.sh b/src/qt/res/movies/makespinner.sh index 8bc2e8c6a4..6e4fd4059d 100755 --- a/src/qt/res/movies/makespinner.sh +++ b/src/qt/res/movies/makespinner.sh @@ -1,13 +1,14 @@ #!/usr/bin/env bash # Copyright (c) 2014-2015 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. +export LC_ALL=C FRAMEDIR=$(dirname $0) for i in {0..35} do frame=$(printf "%03d" $i) angle=$((i * 10)) convert $FRAMEDIR/../src/spinner.png -background "rgba(0,0,0,0.0)" -distort SRT $angle $FRAMEDIR/spinner-$frame.png done diff --git a/test/functional/test_framework/tests/run_self_tests.sh b/test/functional/test_framework/tests/run_self_tests.sh index 0e8c21b7ab..749c71a17b 100644 --- a/test/functional/test_framework/tests/run_self_tests.sh +++ b/test/functional/test_framework/tests/run_self_tests.sh @@ -1,53 +1,55 @@ #!/bin/sh # Copyright (c) 2017 The Bitcoin developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Executes the test framework self-tests located in # qa/rpc-tests/test_framework/tests. # # You should be able to call this script from pretty much anywhere. # It takes care of setting up the PYTHONPATH so tests can run. +export LC_ALL=C + # Enable exit on any error. set -e # Save folder from which script was called. # We may need to return after looking for the base folder. start_folder="$(pwd)" if [ -d qa/rpc-tests ] then # called from top level RPC_TESTS_DIR=$(pwd)/qa/rpc-tests elif [ -d ../qa/rpc-tests ] then # called from out of tree build RPC_TESTS_DIR=$(cd ../qa/rpc-tests && pwd) else # chop off the script's filename to get path scriptpath=$(dirname $0) RPC_TESTS_DIR=$(cd $scriptpath/../.. && pwd) fi export PYTHONPATH="$PYTHONPATH:$RPC_TESTS_DIR" # Go to where the tests are located cd $RPC_TESTS_DIR/test_framework/tests echo "Running test framework self-tests..." # Run all the Python tests we find there. for t in *.py do echo "$(date -u): Starting self-test: $t" SRCDIR=$RPC_TESTS_DIR/../.. python3 ./$t echo "$(date -u): Finished self-test: $t" echo done # Return to calling folder cd "$start_folder" echo "Completed test framework self-tests." diff --git a/test/lint/lint-boost-dependencies.sh b/test/lint/lint-boost-dependencies.sh index 4d13e88422..f17a2f916a 100755 --- a/test/lint/lint-boost-dependencies.sh +++ b/test/lint/lint-boost-dependencies.sh @@ -1,73 +1,75 @@ #!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Guard against accidental introduction of new Boost dependencies. +export LC_ALL=C + EXPECTED_BOOST_INCLUDES=( boost/algorithm/string.hpp boost/algorithm/string/classification.hpp boost/algorithm/string/predicate.hpp boost/algorithm/string/replace.hpp boost/algorithm/string/split.hpp boost/assign/std/vector.hpp boost/bind.hpp boost/chrono/chrono.hpp boost/date_time/posix_time/posix_time.hpp boost/filesystem.hpp boost/filesystem/fstream.hpp boost/interprocess/sync/file_lock.hpp boost/lexical_cast.hpp boost/multi_index/composite_key.hpp boost/multi_index/hashed_index.hpp boost/multi_index/member.hpp boost/multi_index/ordered_index.hpp boost/multi_index/sequenced_index.hpp boost/multi_index_container.hpp boost/noncopyable.hpp boost/optional.hpp boost/preprocessor/cat.hpp boost/preprocessor/stringize.hpp boost/range/iterator.hpp boost/range/adaptor/sliced.hpp boost/scoped_array.hpp boost/signals2/connection.hpp boost/signals2/last_value.hpp boost/signals2/signal.hpp boost/test/unit_test.hpp boost/thread.hpp boost/thread/condition_variable.hpp boost/thread/locks.hpp boost/thread/mutex.hpp boost/thread/shared_mutex.hpp boost/thread/thread.hpp boost/variant.hpp boost/variant/apply_visitor.hpp boost/variant/static_visitor.hpp ) for BOOST_INCLUDE in $(git grep '^#include ' | sort -u); do IS_EXPECTED_INCLUDE=0 for EXPECTED_BOOST_INCLUDE in "${EXPECTED_BOOST_INCLUDES[@]}"; do if [[ "${BOOST_INCLUDE}" == "${EXPECTED_BOOST_INCLUDE}" ]]; then IS_EXPECTED_INCLUDE=1 break fi done if [[ ${IS_EXPECTED_INCLUDE} == 0 ]]; then echo "A new Boost dependency in the form of \"${BOOST_INCLUDE}\" appears to have been introduced:" git grep "${BOOST_INCLUDE}" -- "*.cpp" "*.h" echo fi done for EXPECTED_BOOST_INCLUDE in "${EXPECTED_BOOST_INCLUDES[@]}"; do if ! git grep -q "^#include <${EXPECTED_BOOST_INCLUDE}>" -- "*.cpp" "*.h"; then echo "Good job! The Boost dependency \"${EXPECTED_BOOST_INCLUDE}\" is no longer used." echo "Please remove it from EXPECTED_BOOST_INCLUDES in $0" echo "to make sure this dependency is not accidentally reintroduced." echo fi done diff --git a/test/lint/lint-tests.sh b/test/lint/lint-tests.sh index 0581e85b59..946c06e72c 100755 --- a/test/lint/lint-tests.sh +++ b/test/lint/lint-tests.sh @@ -1,34 +1,36 @@ #!/usr/bin/env bash # # Copyright (c) 2018 The Bitcoin Core developers # Copyright (c) 2019 The Bitcoin developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. # # Check the test suite naming conventions +export LC_ALL=C + TOPDIR=${TOPDIR:-$(git rev-parse --show-toplevel)} NAMING_INCONSISTENCIES=$(git grep -E '^BOOST_FIXTURE_TEST_SUITE\(' -- \ "${1}" | grep -vE '/(.*?)\.cpp:BOOST_FIXTURE_TEST_SUITE\(\1, .*\)$') if [[ ${NAMING_INCONSISTENCIES} != "" ]]; then echo "The test suite in file src/test/foo_tests.cpp should be named" echo "\"foo_tests\". Please make sure the following test suites follow" echo "that convention:" echo echo "${NAMING_INCONSISTENCIES}" fi TEST_SUITE_NAME_COLLISIONS=$(git grep -E '^BOOST_FIXTURE_TEST_SUITE\(' -- \ "${TOPDIR}/src/test/**.cpp" \ "${TOPDIR}/src/rpc/test/**.cpp" \ "${TOPDIR}/src/wallet/test/**.cpp" | cut -f2 -d'(' | cut -f1 -d, | \ sort | uniq -d) if [[ ${TEST_SUITE_NAME_COLLISIONS} != "" ]]; then echo "Test suite names must be unique. The following test suite names" echo "appear to be used more than once:" echo echo "${TEST_SUITE_NAME_COLLISIONS}" fi exit 0