diff --git a/.arclint b/.arclint index 20c6353a39..453e1badba 100644 --- a/.arclint +++ b/.arclint @@ -1,29 +1,33 @@ { "linters": { "generated": { "type": "generated" }, "clang-format": { "type": "clang-format", "version": "7.0", "bin": ["clang-format-7", "clang-format"], "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ] }, "autopep8": { "type": "autopep8", "include": "(\\.py$)" }, "lint-format-strings": { "type": "script-and-regex", "include": "(^src/.*\\.(h|c|cpp)$)", "exclude": [ "(^src/(secp256k1|univalue|leveldb)/)" ], "script-and-regex.script": "test/lint/lint-format-strings.sh", "script-and-regex.regex": "/^(?P.+): (?P.+:.+)$/m" + }, + "check-doc": { + "type": "check-doc", + "include": "(^src/.*\\.(h|c|cpp)$)" } } } diff --git a/arcanist/__phutil_library_map__.php b/arcanist/__phutil_library_map__.php index 059ec6d174..7dba653407 100644 --- a/arcanist/__phutil_library_map__.php +++ b/arcanist/__phutil_library_map__.php @@ -1,20 +1,22 @@ 2, 'class' => array( 'AutoPEP8FormatLinter' => 'linter/AutoPEP8Linter.php', + 'CheckDocLinter' => 'linter/CheckDocLinter.php', 'ClangFormatLinter' => 'linter/ClangFormatLinter.php', ), 'function' => array(), 'xmap' => array( 'AutoPEP8FormatLinter' => 'ArcanistExternalLinter', + 'CheckDocLinter' => 'ArcanistExternalLinter', 'ClangFormatLinter' => 'ArcanistExternalLinter', ), )); diff --git a/arcanist/linter/CheckDocLinter.php b/arcanist/linter/CheckDocLinter.php new file mode 100644 index 0000000000..8aa722ca99 --- /dev/null +++ b/arcanist/linter/CheckDocLinter.php @@ -0,0 +1,103 @@ +getProjectRoot()); + } + + public function shouldUseInterpreter() { + return true; + } + + public function getDefaultInterpreter() { + return "python3"; + } + + public function getInstallInstructions() { + return pht('The test/lint/check-doc.py script is part of the bitcoin-abc project'); + } + + public function shouldExpectCommandErrors() { + return false; + } + + protected function getMandatoryFlags() { + return array( + ); + } + + protected function parseLinterOutput($path, $err, $stdout, $stderr) { + /* Split stdout: + * 0 => Empty (before first 'Args' occurence) + * 1 => Args used: count + * 2 => Args documented: count + * 3 => Args undocumented: count and list + * 4 => Args unknown: count and list + */ + $stdoutExploded = preg_split('/Args/', $stdout); + + $undocumented = $stdoutExploded[3]; + $unknown = $stdoutExploded[4]; + + $messages = array(); + + // Undocumented arguments + $match = preg_match_all('/-[\w|-]+/', $undocumented, $args); + foreach($args[0] as $arg) { + $messages[] = id(new ArcanistLintMessage()) + ->setGranularity(ArcanistLinter::GRANULARITY_GLOBAL) + ->setCode('ARGDOC') + ->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR) + ->setName('Undocumented argument') + ->setDescription("'$arg' is undocumented."); + } + + // Unknown arguments + $match = preg_match_all('/-[\w|-]+/', $unknown, $args); + foreach($args[0] as $arg) { + $messages[] = id(new ArcanistLintMessage()) + ->setGranularity(ArcanistLinter::GRANULARITY_GLOBAL) + ->setCode('ARGDOC') + ->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR) + ->setName('Unknown argument') + ->setDescription("'$arg' is documented but not used."); + } + + return $messages; + } +} + +?> diff --git a/doc/release-process.md b/doc/release-process.md index 0684be0152..553d5d4cd0 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -1,68 +1,68 @@ Bitcoin ABC Release Process =========================== ## Before Release 1. Check configuration - Check features planned for the release are implemented and documented (or more informally, that the Release Manager agrees it is feature complete) - Check that finished tasks / tickets are marked as resolved 2. Verify tests passed - Any known issues or limitations should be documented in release notes - Known bugs should have tickets - - Run the `contrib/devtools/check-doc.py` script and ensure there is no undocumented argument + - Run `arc lint --everything` and check there is no linter error - Verify IBD without checkpoints and without assumevalid. 3. Update the documents / code which needs to be updated every release - Check that doc/release-notes.md is complete, and fill in any missing items. - Update [bips.md](/doc/bips.md) to account for changes since the last release. - (major releases) Update [`BLOCK_CHAIN_SIZE`](/src/qt/intro.cpp) to the current size plus some overhead. - Update `src/chainparams.cpp` defaultAssumeValid and nMinimumChainWork with information from the getblockhash rpc. - The selected value must not be orphaned so it may be useful to set the value two blocks back from the tip. - Testnet should be set some tens of thousands back from the tip due to reorgs there. - This update should be reviewed with a reindex-chainstate with assumevalid=0 to catch any defect that causes rejection of blocks in the past history. - Regenerate manpages (run `contrib/devtools/gen-manpages.sh`, or for out-of-tree builds run `BUILDDIR=$PWD/build contrib/devtools/gen-manpages.sh`). - Update seeds as per [contrib/seeds/README.md](/contrib/seeds/README.md) 4. Add git tag for release ## Release 5. Create Gitian Builds (see [gitian-building.md](/doc/gitian-building.md)) 6. Verify matching gitian builds, gather signatures 7. Upload gitian build to [bitcoinabc.org](https://download.bitcoinabc.org/) 8. Create a [GitHub release](https://github.com/Bitcoin-ABC/bitcoin-abc/releases). The Github release name should be the same as the tag (without the prepended 'v'), and the contents of the release notes should be copied from release-notes.md. ## After Release 9. Notify maintainers of Ubuntu PPA, AUR, and Docker images to build their packages. 10. Increment version number in: - doc/Doxyfile - doc/release-notes.md (and copy existing one to versioned doc/release-notes/*.md) - configure.ac - src/config/CMakeLists.txt - contrib/gitian-descriptors/*.yml (before a new major release) 11. Update version number on www.bitcoinabc.org 12. Publish signed checksums (various places, e.g. blog, reddit/r/BitcoinABC) 13. Announce Release: - [Reddit](https://www.reddit.com/r/BitcoinABC/) - Twitter @Bitcoin_ABC - Public slack channels friendly to Bitcoin ABC announcements (eg. #abc-announce on BTCforks, #hardfork on BTCchat) diff --git a/test/lint/check-doc.py b/test/lint/check-doc.py index 6ef9821ccf..2163204ac2 100755 --- a/test/lint/check-doc.py +++ b/test/lint/check-doc.py @@ -1,82 +1,80 @@ #!/usr/bin/env python3 # Copyright (c) 2015-2016 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. ''' This checks if all command line args are documented. Return value is 0 to indicate no error. Author: @MarcoFalke ''' from subprocess import check_output from pprint import PrettyPrinter import re import sys FOLDER_SRC = 'src' FOLDER_TEST = 'src/test/' PATH_SRC = '`git rev-parse --show-toplevel`/{}'.format(FOLDER_SRC) PATH_TEST = '`git rev-parse --show-toplevel`/{}'.format(FOLDER_TEST) GREP_ARGS_REGEX = r"egrep -rIzo '((Is|Get)(Bool)?Arg(s|Set)?\((\s)*)\"\-[^\"]+?\"' {}" CMD_GREP_ARGS_SRC = GREP_ARGS_REGEX.format(PATH_SRC) CMD_GREP_ARGS_TEST = GREP_ARGS_REGEX.format(PATH_TEST) CMD_GREP_DOCS = r"egrep -rIzo 'HelpMessageOpt\((\s)*\"\-[^\"=]+?(=|\")' {}".format( PATH_SRC) REGEX_ARG = re.compile( r'(?:(?:Is|Get)(?:Bool)?Arg(?:s|Set)?\((?:\s)*)\"(\-[^\"]+?)\"') REGEX_DOC = re.compile(r'HelpMessageOpt\((?:\s)*\"(\-[^\"=]+?)(?:=|\")') # list unsupported, deprecated and duplicate args as they need no documentation SET_DOC_OPTIONAL = set(['-benchmark', '-blockminsize', '-dbcrashratio', '-debugnet', '-forcecompactdb', '-help', '-parkdeepreorg', '-promiscuousmempoolflags', '-replayprotectionactivationtime', '-rpcssl', '-socks', '-tor', '-whitelistalwaysrelay']) # list false positive unknows arguments SET_FALSE_POSITIVE_UNKNOWNS = set(['-nodebug', '-zmqpubhashblock', '-zmqpubhashtx', '-zmqpubrawblock', '-zmqpubrawtx']) def main(): used = check_output(CMD_GREP_ARGS_SRC, shell=True).decode() tested = check_output(CMD_GREP_ARGS_TEST, shell=True).decode() docd = check_output(CMD_GREP_DOCS, shell=True).decode() args_used = set(re.findall(REGEX_ARG, used)) args_used -= set(re.findall(REGEX_ARG, tested)) args_used |= SET_FALSE_POSITIVE_UNKNOWNS args_docd = set(re.findall(REGEX_DOC, docd)) args_need_doc = args_used - args_docd - SET_DOC_OPTIONAL args_unknown = args_docd - args_used pp = PrettyPrinter() print("Args used : {}".format(len(args_used))) print("Args documented : {}".format(len(args_docd))) print("Args undocumented: {} ({} don't need documentation)".format( len(args_need_doc), len(SET_DOC_OPTIONAL))) pp.pprint(args_need_doc) print("Args unknown : {}".format(len(args_unknown))) pp.pprint(args_unknown) - sys.exit(len(args_need_doc)) - if __name__ == "__main__": main()