diff options
Diffstat (limited to 'contrib')
23 files changed, 179 insertions, 902 deletions
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 7ac8aa39d3..a0b6225345 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -2,12 +2,6 @@ Contents ======== This directory contains tools for developers working on this repository. -check-doc.py -============ - -Check if all command line args are documented. The return value indicates the -number of undocumented args. - clang-format-diff.py =================== @@ -93,23 +87,6 @@ example: BUILDDIR=$PWD/build contrib/devtools/gen-manpages.sh ``` -git-subtree-check.sh -==================== - -Run this script from the root of the repository to verify that a subtree matches the contents of -the commit it claims to have been updated to. - -To use, make sure that you have fetched the upstream repository branch in which the subtree is -maintained: -* for `src/secp256k1`: https://github.com/bitcoin-core/secp256k1.git (branch master) -* for `src/leveldb`: https://github.com/bitcoin-core/leveldb.git (branch bitcoin-fork) -* for `src/univalue`: https://github.com/bitcoin-core/univalue.git (branch master) -* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master) - -Usage: `git-subtree-check.sh DIR (COMMIT)` - -`COMMIT` may be omitted, in which case `HEAD` is used. - github-merge.py =============== diff --git a/contrib/devtools/check-doc.py b/contrib/devtools/check-doc.py deleted file mode 100755 index de5719eb29..0000000000 --- a/contrib/devtools/check-doc.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2015-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. - -''' -This checks if all command line args are documented. -Return value is 0 to indicate no error. - -Author: @MarcoFalke -''' - -from subprocess import check_output -import re -import sys - -FOLDER_GREP = 'src' -FOLDER_TEST = 'src/test/' -REGEX_ARG = '(?:ForceSet|SoftSet|Get|Is)(?:Bool)?Args?(?:Set)?\("(-[^"]+)"' -REGEX_DOC = 'AddArg\("(-[^"=]+?)(?:=|")' -CMD_ROOT_DIR = '`git rev-parse --show-toplevel`/{}'.format(FOLDER_GREP) -CMD_GREP_ARGS = r"git grep --perl-regexp '{}' -- {} ':(exclude){}'".format(REGEX_ARG, CMD_ROOT_DIR, FOLDER_TEST) -CMD_GREP_DOCS = r"git grep --perl-regexp '{}' {}".format(REGEX_DOC, CMD_ROOT_DIR) -# list unsupported, deprecated and duplicate args as they need no documentation -SET_DOC_OPTIONAL = set(['-rpcssl', '-benchmark', '-h', '-help', '-socks', '-tor', '-debugnet', '-whitelistalwaysrelay', '-prematurewitness', '-walletprematurewitness', '-promiscuousmempoolflags', '-blockminsize', '-dbcrashratio', '-forcecompactdb', '-usehd']) - - -def main(): - used = check_output(CMD_GREP_ARGS, shell=True, universal_newlines=True) - docd = check_output(CMD_GREP_DOCS, shell=True, universal_newlines=True) - - args_used = set(re.findall(re.compile(REGEX_ARG), used)) - args_docd = set(re.findall(re.compile(REGEX_DOC), docd)).union(SET_DOC_OPTIONAL) - args_need_doc = args_used.difference(args_docd) - args_unknown = args_docd.difference(args_used) - - print("Args used : {}".format(len(args_used))) - print("Args documented : {}".format(len(args_docd))) - print("Args undocumented: {}".format(len(args_need_doc))) - print(args_need_doc) - print("Args unknown : {}".format(len(args_unknown))) - print(args_unknown) - - sys.exit(len(args_need_doc)) - - -if __name__ == "__main__": - main() diff --git a/contrib/devtools/check-rpc-mappings.py b/contrib/devtools/check-rpc-mappings.py deleted file mode 100755 index 7e96852c5c..0000000000 --- a/contrib/devtools/check-rpc-mappings.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python3 -# 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. -"""Check RPC argument consistency.""" - -from collections import defaultdict -import os -import re -import sys - -# Source files (relative to root) to scan for dispatch tables -SOURCES = [ - "src/rpc/server.cpp", - "src/rpc/blockchain.cpp", - "src/rpc/mining.cpp", - "src/rpc/misc.cpp", - "src/rpc/net.cpp", - "src/rpc/rawtransaction.cpp", - "src/wallet/rpcwallet.cpp", -] -# Source file (relative to root) containing conversion mapping -SOURCE_CLIENT = 'src/rpc/client.cpp' -# Argument names that should be ignored in consistency checks -IGNORE_DUMMY_ARGS = {'dummy', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4', 'arg5', 'arg6', 'arg7', 'arg8', 'arg9'} - -class RPCCommand: - def __init__(self, name, args): - self.name = name - self.args = args - -class RPCArgument: - def __init__(self, names, idx): - self.names = names - self.idx = idx - self.convert = False - -def parse_string(s): - assert s[0] == '"' - assert s[-1] == '"' - return s[1:-1] - -def process_commands(fname): - """Find and parse dispatch table in implementation file `fname`.""" - cmds = [] - in_rpcs = False - with open(fname, "r") as f: - for line in f: - line = line.rstrip() - if not in_rpcs: - if re.match("static const CRPCCommand .*\[\] =", line): - in_rpcs = True - else: - if line.startswith('};'): - in_rpcs = False - elif '{' in line and '"' in line: - m = re.search('{ *("[^"]*"), *("[^"]*"), *&([^,]*), *{([^}]*)} *},', line) - assert m, 'No match to table expression: %s' % line - name = parse_string(m.group(2)) - args_str = m.group(4).strip() - if args_str: - args = [RPCArgument(parse_string(x.strip()).split('|'), idx) for idx, x in enumerate(args_str.split(','))] - else: - args = [] - cmds.append(RPCCommand(name, args)) - assert not in_rpcs and cmds, "Something went wrong with parsing the C++ file: update the regexps" - return cmds - -def process_mapping(fname): - """Find and parse conversion table in implementation file `fname`.""" - cmds = [] - in_rpcs = False - with open(fname, "r") as f: - for line in f: - line = line.rstrip() - if not in_rpcs: - if line == 'static const CRPCConvertParam vRPCConvertParams[] =': - in_rpcs = True - else: - if line.startswith('};'): - in_rpcs = False - elif '{' in line and '"' in line: - m = re.search('{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *},', line) - assert m, 'No match to table expression: %s' % line - name = parse_string(m.group(1)) - idx = int(m.group(2)) - argname = parse_string(m.group(3)) - cmds.append((name, idx, argname)) - assert not in_rpcs and cmds - return cmds - -def main(): - root = sys.argv[1] - - # Get all commands from dispatch tables - cmds = [] - for fname in SOURCES: - cmds += process_commands(os.path.join(root, fname)) - - cmds_by_name = {} - for cmd in cmds: - cmds_by_name[cmd.name] = cmd - - # Get current convert mapping for client - client = SOURCE_CLIENT - mapping = set(process_mapping(os.path.join(root, client))) - - print('* Checking consistency between dispatch tables and vRPCConvertParams') - - # Check mapping consistency - errors = 0 - for (cmdname, argidx, argname) in mapping: - try: - rargnames = cmds_by_name[cmdname].args[argidx].names - except IndexError: - print('ERROR: %s argument %i (named %s in vRPCConvertParams) is not defined in dispatch table' % (cmdname, argidx, argname)) - errors += 1 - continue - if argname not in rargnames: - print('ERROR: %s argument %i is named %s in vRPCConvertParams but %s in dispatch table' % (cmdname, argidx, argname, rargnames), file=sys.stderr) - errors += 1 - - # Check for conflicts in vRPCConvertParams conversion - # All aliases for an argument must either be present in the - # conversion table, or not. Anything in between means an oversight - # and some aliases won't work. - for cmd in cmds: - for arg in cmd.args: - convert = [((cmd.name, arg.idx, argname) in mapping) for argname in arg.names] - if any(convert) != all(convert): - print('ERROR: %s argument %s has conflicts in vRPCConvertParams conversion specifier %s' % (cmd.name, arg.names, convert)) - errors += 1 - arg.convert = all(convert) - - # Check for conversion difference by argument name. - # It is preferable for API consistency that arguments with the same name - # have the same conversion, so bin by argument name. - all_methods_by_argname = defaultdict(list) - converts_by_argname = defaultdict(list) - for cmd in cmds: - for arg in cmd.args: - for argname in arg.names: - all_methods_by_argname[argname].append(cmd.name) - converts_by_argname[argname].append(arg.convert) - - for argname, convert in converts_by_argname.items(): - if all(convert) != any(convert): - if argname in IGNORE_DUMMY_ARGS: - # these are testing or dummy, don't warn for them - continue - print('WARNING: conversion mismatch for argument named %s (%s)' % - (argname, list(zip(all_methods_by_argname[argname], converts_by_argname[argname])))) - - sys.exit(errors > 0) - - -if __name__ == '__main__': - main() diff --git a/contrib/devtools/commit-script-check.sh b/contrib/devtools/commit-script-check.sh deleted file mode 100755 index 1c9dbc7f68..0000000000 --- a/contrib/devtools/commit-script-check.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# 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. - -# This simple script checks for commits beginning with: scripted-diff: -# If found, looks for a script between the lines -BEGIN VERIFY SCRIPT- and -# -END VERIFY SCRIPT-. If no ending is found, it reads until the end of the -# commit message. - -# The resulting script should exactly transform the previous commit into the current -# one. Any remaining diff signals an error. - -if test "x$1" = "x"; then - echo "Usage: $0 <commit>..." - exit 1 -fi - -RET=0 -PREV_BRANCH=`git name-rev --name-only HEAD` -PREV_HEAD=`git rev-parse HEAD` -for i in `git rev-list --reverse $1`; do - if git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:"; then - git checkout --quiet $i^ || exit - SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`" - if test "x$SCRIPT" = "x"; then - echo "Error: missing script for: $i" - echo "Failed" - RET=1 - else - echo "Running script for: $i" - echo "$SCRIPT" - eval "$SCRIPT" - git --no-pager diff --exit-code $i && echo "OK" || (echo "Failed"; false) || RET=1 - fi - git reset --quiet --hard HEAD - else - if git rev-list "--format=%b" -n1 $i | grep -q '^-\(BEGIN\|END\)[ a-zA-Z]*-$'; then - echo "Error: script block marker but no scripted-diff in title" - echo "Failed" - RET=1 - fi - fi -done -git checkout --quiet $PREV_BRANCH 2>/dev/null || git checkout --quiet $PREV_HEAD -exit $RET diff --git a/contrib/devtools/git-subtree-check.sh b/contrib/devtools/git-subtree-check.sh deleted file mode 100755 index 184951715e..0000000000 --- a/contrib/devtools/git-subtree-check.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -# Copyright (c) 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. - -DIR="$1" -COMMIT="$2" -if [ -z "$COMMIT" ]; then - COMMIT=HEAD -fi - -# Taken from git-subtree (Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>) -find_latest_squash() -{ - dir="$1" - sq= - main= - sub= - git log --grep="^git-subtree-dir: $dir/*\$" \ - --pretty=format:'START %H%n%s%n%n%b%nEND%n' "$COMMIT" | - while read a b _; do - case "$a" in - START) sq="$b" ;; - git-subtree-mainline:) main="$b" ;; - git-subtree-split:) sub="$b" ;; - END) - if [ -n "$sub" ]; then - if [ -n "$main" ]; then - # a rejoin commit? - # Pretend its sub was a squash. - sq="$sub" - fi - echo "$sq" "$sub" - break - fi - sq= - main= - sub= - ;; - esac - done -} - -# find latest subtree update -latest_squash="$(find_latest_squash "$DIR")" -if [ -z "$latest_squash" ]; then - echo "ERROR: $DIR is not a subtree" >&2 - exit 2 -fi -set $latest_squash -old=$1 -rev=$2 - -# get the tree in the current commit -tree_actual=$(git ls-tree -d "$COMMIT" "$DIR" | head -n 1) -if [ -z "$tree_actual" ]; then - echo "FAIL: subtree directory $DIR not found in $COMMIT" >&2 - exit 1 -fi -set $tree_actual -tree_actual_type=$2 -tree_actual_tree=$3 -echo "$DIR in $COMMIT currently refers to $tree_actual_type $tree_actual_tree" -if [ "d$tree_actual_type" != "dtree" ]; then - echo "FAIL: subtree directory $DIR is not a tree in $COMMIT" >&2 - exit 1 -fi - -# get the tree at the time of the last subtree update -tree_commit=$(git show -s --format="%T" $old) -echo "$DIR in $COMMIT was last updated in commit $old (tree $tree_commit)" - -# ... and compare the actual tree with it -if [ "$tree_actual_tree" != "$tree_commit" ]; then - git diff $tree_commit $tree_actual_tree >&2 - echo "FAIL: subtree directory was touched without subtree merge" >&2 - exit 1 -fi - -# get the tree in the subtree commit referred to -if [ "d$(git cat-file -t $rev 2>/dev/null)" != dcommit ]; then - echo "subtree commit $rev unavailable: cannot compare" >&2 - exit -fi -tree_subtree=$(git show -s --format="%T" $rev) -echo "$DIR in $COMMIT was last updated to upstream commit $rev (tree $tree_subtree)" - -# ... and compare the actual tree with it -if [ "$tree_actual_tree" != "$tree_subtree" ]; then - echo "FAIL: subtree update commit differs from upstream tree!" >&2 - exit 1 -fi - -echo "GOOD" diff --git a/contrib/devtools/lint-all.sh b/contrib/devtools/lint-all.sh deleted file mode 100755 index b6d86959c6..0000000000 --- a/contrib/devtools/lint-all.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/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. -# -# This script runs all contrib/devtools/lint-*.sh files, and fails if any exit -# with a non-zero status code. - -set -u - -SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}") -LINTALL=$(basename "${BASH_SOURCE[0]}") - -for f in "${SCRIPTDIR}"/lint-*.sh; do - if [ "$(basename "$f")" != "$LINTALL" ]; then - if ! "$f"; then - echo "^---- failure generated from $f" - exit 1 - fi - fi -done diff --git a/contrib/devtools/lint-include-guards.sh b/contrib/devtools/lint-include-guards.sh deleted file mode 100755 index 6a0dd556bb..0000000000 --- a/contrib/devtools/lint-include-guards.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/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. -# -# Check include guards. - -HEADER_ID_PREFIX="BITCOIN_" -HEADER_ID_SUFFIX="_H" - -REGEXP_EXCLUDE_FILES_WITH_PREFIX="src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)" - -EXIT_CODE=0 -for HEADER_FILE in $(git ls-files -- "*.h" | grep -vE "^${REGEXP_EXCLUDE_FILES_WITH_PREFIX}") -do - HEADER_ID_BASE=$(cut -f2- -d/ <<< "${HEADER_FILE}" | sed "s/\.h$//g" | tr / _ | tr "[:lower:]" "[:upper:]") - HEADER_ID="${HEADER_ID_PREFIX}${HEADER_ID_BASE}${HEADER_ID_SUFFIX}" - if [[ $(grep -cE "^#(ifndef|define) ${HEADER_ID}" "${HEADER_FILE}") != 2 ]]; then - echo "${HEADER_FILE} seems to be missing the expected include guard:" - echo " #ifndef ${HEADER_ID}" - echo " #define ${HEADER_ID}" - echo " ..." - echo " #endif // ${HEADER_ID}" - echo - EXIT_CODE=1 - fi -done -exit ${EXIT_CODE} diff --git a/contrib/devtools/lint-includes.sh b/contrib/devtools/lint-includes.sh deleted file mode 100755 index f54be46b52..0000000000 --- a/contrib/devtools/lint-includes.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/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. -# -# Check for duplicate includes. - -filter_suffix() { - git ls-files | grep -E "^src/.*\.${1}"'$' | grep -Ev "/(leveldb|secp256k1|univalue)/" -} - -EXIT_CODE=0 -for HEADER_FILE in $(filter_suffix h); do - DUPLICATE_INCLUDES_IN_HEADER_FILE=$(grep -E "^#include " < "${HEADER_FILE}" | sort | uniq -d) - if [[ ${DUPLICATE_INCLUDES_IN_HEADER_FILE} != "" ]]; then - echo "Duplicate include(s) in ${HEADER_FILE}:" - echo "${DUPLICATE_INCLUDES_IN_HEADER_FILE}" - echo - EXIT_CODE=1 - fi -done -for CPP_FILE in $(filter_suffix cpp); do - DUPLICATE_INCLUDES_IN_CPP_FILE=$(grep -E "^#include " < "${CPP_FILE}" | sort | uniq -d) - if [[ ${DUPLICATE_INCLUDES_IN_CPP_FILE} != "" ]]; then - echo "Duplicate include(s) in ${CPP_FILE}:" - echo "${DUPLICATE_INCLUDES_IN_CPP_FILE}" - echo - EXIT_CODE=1 - fi -done -exit ${EXIT_CODE} diff --git a/contrib/devtools/lint-logs.sh b/contrib/devtools/lint-logs.sh deleted file mode 100755 index 35be13ec19..0000000000 --- a/contrib/devtools/lint-logs.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/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. -# -# Check that all logs are terminated with '\n' -# -# Some logs are continued over multiple lines. They should be explicitly -# commented with \* Continued *\ -# -# There are some instances of LogPrintf() in comments. Those can be -# ignored - - -UNTERMINATED_LOGS=$(git grep --extended-regexp "LogPrintf?\(" -- "*.cpp" | \ - grep -v '\\n"' | \ - grep -v "/\* Continued \*/" | \ - grep -v "LogPrint()" | \ - grep -v "LogPrintf()") -if [[ ${UNTERMINATED_LOGS} != "" ]]; then - echo "All calls to LogPrintf() and LogPrint() should be terminated with \\n" - echo - echo "${UNTERMINATED_LOGS}" - exit 1 -fi diff --git a/contrib/devtools/lint-python-shebang.sh b/contrib/devtools/lint-python-shebang.sh deleted file mode 100755 index f5c5971c03..0000000000 --- a/contrib/devtools/lint-python-shebang.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# Shebang must use python3 (not python or python2) -EXIT_CODE=0 -for PYTHON_FILE in $(git ls-files -- "*.py"); do - if [[ $(head -c 2 "${PYTHON_FILE}") == "#!" && - $(head -n 1 "${PYTHON_FILE}") != "#!/usr/bin/env python3" ]]; then - echo "Missing shebang \"#!/usr/bin/env python3\" in ${PYTHON_FILE} (do not use python or python2)" - EXIT_CODE=1 - fi -done -exit ${EXIT_CODE} diff --git a/contrib/devtools/lint-python.sh b/contrib/devtools/lint-python.sh deleted file mode 100755 index 7d3555b6d4..0000000000 --- a/contrib/devtools/lint-python.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh -# -# 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. -# -# Check for specified flake8 warnings in python files. - -# E101 indentation contains mixed spaces and tabs -# E112 expected an indented block -# E113 unexpected indentation -# E115 expected an indented block (comment) -# E116 unexpected indentation (comment) -# E125 continuation line with same indent as next logical line -# E129 visually indented line with same indent as next logical line -# E131 continuation line unaligned for hanging indent -# E133 closing bracket is missing indentation -# E223 tab before operator -# E224 tab after operator -# E242 tab after ',' -# E266 too many leading '#' for block comment -# E271 multiple spaces after keyword -# E272 multiple spaces before keyword -# E273 tab after keyword -# E274 tab before keyword -# E275 missing whitespace after keyword -# E304 blank lines found after function decorator -# E306 expected 1 blank line before a nested definition -# E401 multiple imports on one line -# E402 module level import not at top of file -# E502 the backslash is redundant between brackets -# E701 multiple statements on one line (colon) -# E702 multiple statements on one line (semicolon) -# E703 statement ends with a semicolon -# E714 test for object identity should be "is not" -# E721 do not compare types, use "isinstance()" -# E741 do not use variables named "l", "O", or "I" -# E742 do not define classes named "l", "O", or "I" -# E743 do not define functions named "l", "O", or "I" -# E901 SyntaxError: invalid syntax -# E902 TokenError: EOF in multi-line string -# F401 module imported but unused -# F402 import module from line N shadowed by loop variable -# F404 future import(s) name after other statements -# F406 "from module import *" only allowed at module level -# F407 an undefined __future__ feature name was imported -# F601 dictionary key name repeated with different values -# F602 dictionary key variable name repeated with different values -# F621 too many expressions in an assignment with star-unpacking -# F622 two or more starred expressions in an assignment (a, *b, *c = d) -# F631 assertion test is a tuple, which are always True -# F701 a break statement outside of a while or for loop -# F702 a continue statement outside of a while or for loop -# F703 a continue statement in a finally block in a loop -# F704 a yield or yield from statement outside of a function -# F705 a return statement with arguments inside a generator -# F706 a return statement outside of a function/method -# F707 an except: block as not the last exception handler -# F811 redefinition of unused name from line N -# F812 list comprehension redefines 'foo' from line N -# F821 undefined name 'Foo' -# F822 undefined name name in __all__ -# F823 local variable name … referenced before assignment -# F831 duplicate argument name in function definition -# F841 local variable 'foo' is assigned to but never used -# W191 indentation contains tabs -# W291 trailing whitespace -# W292 no newline at end of file -# W293 blank line contains whitespace -# W504 line break after binary operator -# W601 .has_key() is deprecated, use "in" -# W602 deprecated form of raising exception -# W603 "<>" is deprecated, use "!=" -# W604 backticks are deprecated, use "repr()" -# W605 invalid escape sequence "x" -# W606 'async' and 'await' are reserved keywords starting with Python 3.7 - -flake8 --ignore=B,C,E,F,I,N,W --select=E101,E112,E113,E115,E116,E125,E129,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,F401,E901,E902,F402,F404,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W191,W291,W292,W293,W504,W601,W602,W603,W604,W605,W606 . diff --git a/contrib/devtools/lint-shell.sh b/contrib/devtools/lint-shell.sh deleted file mode 100755 index 5f5fa9a925..0000000000 --- a/contrib/devtools/lint-shell.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/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. -# -# Check for shellcheck warnings in shell scripts. - -# Disabled warnings: -# SC2001: See if you can use ${variable//search/replace} instead. -# SC2004: $/${} is unnecessary on arithmetic variables. -# SC2005: Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. -# SC2006: Use $(..) instead of legacy `..`. -# SC2016: Expressions don't expand in single quotes, use double quotes for that. -# SC2028: echo won't expand escape sequences. Consider printf. -# SC2046: Quote this to prevent word splitting. -# SC2048: Use "$@" (with quotes) to prevent whitespace problems. -# SC2066: Since you double quoted this, it will not word split, and the loop will only run once. -# SC2086: Double quote to prevent globbing and word splitting. -# SC2116: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'. -# SC2148: Tips depend on target shell and yours is unknown. Add a shebang. -# SC2162: read without -r will mangle backslashes. -# SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined. -# SC2166: Prefer [ p ] || [ q ] as [ p -o q ] is not well defined. -# SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?. -shellcheck -e SC2001,SC2004,SC2005,SC2006,SC2016,SC2028,SC2046,SC2048,SC2066,SC2086,SC2116,SC2148,SC2162,SC2166,SC2181 \ - $(git ls-files -- "*.sh" | grep -vE 'src/(secp256k1|univalue)/') diff --git a/contrib/devtools/lint-tests.sh b/contrib/devtools/lint-tests.sh deleted file mode 100755 index ffc0660551..0000000000 --- a/contrib/devtools/lint-tests.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/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. -# -# Check the test suite naming conventions - -EXIT_CODE=0 - -NAMING_INCONSISTENCIES=$(git grep -E '^BOOST_FIXTURE_TEST_SUITE\(' -- \ - "src/test/**.cpp" "src/wallet/test/**.cpp" | \ - 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}" - EXIT_CODE=1 -fi - -TEST_SUITE_NAME_COLLISSIONS=$(git grep -E '^BOOST_FIXTURE_TEST_SUITE\(' -- \ - "src/test/**.cpp" "src/wallet/test/**.cpp" | cut -f2 -d'(' | cut -f1 -d, | \ - sort | uniq -d) -if [[ ${TEST_SUITE_NAME_COLLISSIONS} != "" ]]; 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_COLLISSIONS}" - EXIT_CODE=1 -fi - -exit ${EXIT_CODE} diff --git a/contrib/devtools/lint-whitespace.sh b/contrib/devtools/lint-whitespace.sh deleted file mode 100755 index c5d43043d5..0000000000 --- a/contrib/devtools/lint-whitespace.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/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. -# -# Check for new lines in diff that introduce trailing whitespace. - -# We can't run this check unless we know the commit range for the PR. - -while getopts "?" opt; do - case $opt in - ?) - echo "Usage: .lint-whitespace.sh [N]" - echo " TRAVIS_COMMIT_RANGE='<commit range>' .lint-whitespace.sh" - echo " .lint-whitespace.sh -?" - echo "Checks unstaged changes, the previous N commits, or a commit range." - echo "TRAVIS_COMMIT_RANGE='47ba2c3...ee50c9e' .lint-whitespace.sh" - exit 0 - ;; - esac -done - -if [ -z "${TRAVIS_COMMIT_RANGE}" ]; then - if [ "$1" ]; then - TRAVIS_COMMIT_RANGE="HEAD~$1...HEAD" - else - TRAVIS_COMMIT_RANGE="HEAD" - fi -fi - -showdiff() { - if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- "." ":(exclude)depends/patches/" ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/"; then - echo "Failed to get a diff" - exit 1 - fi -} - -showcodediff() { - if ! git diff -U0 "${TRAVIS_COMMIT_RANGE}" -- *.cpp *.h *.md *.py *.sh ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" ":(exclude)doc/release-notes/"; then - echo "Failed to get a diff" - exit 1 - fi -} - -RET=0 - -# Check if trailing whitespace was found in the diff. -if showdiff | grep -E -q '^\+.*\s+$'; then - echo "This diff appears to have added new lines with trailing whitespace." - echo "The following changes were suspected:" - FILENAME="" - SEEN=0 - SEENLN=0 - while read -r line; do - if [[ "$line" =~ ^diff ]]; then - FILENAME="$line" - SEEN=0 - elif [[ "$line" =~ ^@@ ]]; then - LINENUMBER="$line" - SEENLN=0 - else - if [ "$SEEN" -eq 0 ]; then - # The first time a file is seen with trailing whitespace, we print the - # filename (preceded by a newline). - echo - echo "$FILENAME" - SEEN=1 - fi - if [ "$SEENLN" -eq 0 ]; then - echo "$LINENUMBER" - SEENLN=1 - fi - echo "$line" - fi - done < <(showdiff | grep -E '^(diff --git |@@|\+.*\s+$)') - RET=1 -fi - -# Check if tab characters were found in the diff. -if showcodediff | perl -nle '$MATCH++ if m{^\+.*\t}; END{exit 1 unless $MATCH>0}' > /dev/null; then - echo "This diff appears to have added new lines with tab characters instead of spaces." - echo "The following changes were suspected:" - FILENAME="" - SEEN=0 - SEENLN=0 - while read -r line; do - if [[ "$line" =~ ^diff ]]; then - FILENAME="$line" - SEEN=0 - elif [[ "$line" =~ ^@@ ]]; then - LINENUMBER="$line" - SEENLN=0 - else - if [ "$SEEN" -eq 0 ]; then - # The first time a file is seen with a tab character, we print the - # filename (preceded by a newline). - echo - echo "$FILENAME" - SEEN=1 - fi - if [ "$SEENLN" -eq 0 ]; then - echo "$LINENUMBER" - SEENLN=1 - fi - echo "$line" - fi - done < <(showcodediff | perl -nle 'print if m{^(diff --git |@@|\+.*\t)}') - RET=1 -fi - -exit $RET diff --git a/contrib/devtools/update-translations.py b/contrib/devtools/update-translations.py index b36e6968bf..f0098cfcdf 100755 --- a/contrib/devtools/update-translations.py +++ b/contrib/devtools/update-translations.py @@ -30,6 +30,8 @@ SOURCE_LANG = 'bitcoin_en.ts' LOCALE_DIR = 'src/qt/locale' # Minimum number of messages for translation to be considered at all MIN_NUM_MESSAGES = 10 +# Regexp to check for Bitcoin addresses +ADDRESS_REGEXP = re.compile('([13]|bc1)[a-zA-Z0-9]{30,}') def check_at_repository_root(): if not os.path.exists('.git'): @@ -122,6 +124,12 @@ def escape_cdata(text): text = text.replace('"', '"') return text +def contains_bitcoin_addr(text, errors): + if text != None and ADDRESS_REGEXP.search(text) != None: + errors.append('Translation "%s" contains a bitcoin address. This will be removed.' % (text)) + return True + return False + def postprocess_translations(reduce_diff_hacks=False): print('Checking and postprocessing...') @@ -160,7 +168,7 @@ def postprocess_translations(reduce_diff_hacks=False): if translation is None: continue errors = [] - valid = check_format_specifiers(source, translation, errors, numerus) + valid = check_format_specifiers(source, translation, errors, numerus) and not contains_bitcoin_addr(translation, errors) for error in errors: print('%s: %s' % (filename, error)) diff --git a/contrib/gitian-build.sh b/contrib/gitian-build.sh index 94d6a89c7b..5a925f2282 100755 --- a/contrib/gitian-build.sh +++ b/contrib/gitian-build.sh @@ -1,3 +1,4 @@ +#!/bin/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. diff --git a/contrib/init/README.md b/contrib/init/README.md index 1a949f3c07..8d3e57c526 100644 --- a/contrib/init/README.md +++ b/contrib/init/README.md @@ -5,7 +5,7 @@ Upstart: bitcoind.conf OpenRC: bitcoind.openrc bitcoind.openrcconf CentOS: bitcoind.init -OS X: org.bitcoin.bitcoind.plist +macOS: org.bitcoin.bitcoind.plist ``` have been made available to assist packagers in creating node packages here. diff --git a/contrib/verify-commits/README.md b/contrib/verify-commits/README.md index fa492fdd27..aa805ad1b9 100644 --- a/contrib/verify-commits/README.md +++ b/contrib/verify-commits/README.md @@ -7,18 +7,18 @@ are PGP signed (nearly always merge commits), as well as a script to verify commits against a trusted keys list. -Using verify-commits.sh safely +Using verify-commits.py safely ------------------------------ Remember that you can't use an untrusted script to verify itself. This means -that checking out code, then running `verify-commits.sh` against `HEAD` is -_not_ safe, because the version of `verify-commits.sh` that you just ran could +that checking out code, then running `verify-commits.py` against `HEAD` is +_not_ safe, because the version of `verify-commits.py` that you just ran could be backdoored. Instead, you need to use a trusted version of verify-commits prior to checkout to make sure you're checking out only code signed by trusted keys: git fetch origin && \ - ./contrib/verify-commits/verify-commits.sh origin/master && \ + ./contrib/verify-commits/verify-commits.py origin/master && \ git checkout origin/master Note that the above isn't a good UI/UX yet, and needs significant improvements @@ -42,6 +42,6 @@ said key. In order to avoid bumping the root-of-trust `trusted-git-root` file, individual commits which were signed by such a key can be added to the `allow-revsig-commits` file. That way, the PGP signatures are still verified but no new commits can be signed by any expired/revoked key. To easily build a -list of commits which need to be added, verify-commits.sh can be edited to test +list of commits which need to be added, verify-commits.py can be edited to test each commit with BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG set to both 1 and 0, and those which need it set to 1 printed. diff --git a/contrib/verify-commits/allow-incorrect-sha512-commits b/contrib/verify-commits/allow-incorrect-sha512-commits new file mode 100644 index 0000000000..c572806f26 --- /dev/null +++ b/contrib/verify-commits/allow-incorrect-sha512-commits @@ -0,0 +1,2 @@ +f8feaa4636260b599294c7285bcf1c8b7737f74e +8040ae6fc576e9504186f2ae3ff2c8125de1095c diff --git a/contrib/verify-commits/allow-unclean-merge-commits b/contrib/verify-commits/allow-unclean-merge-commits new file mode 100644 index 0000000000..7aab274b9a --- /dev/null +++ b/contrib/verify-commits/allow-unclean-merge-commits @@ -0,0 +1,4 @@ +6052d509105790a26b3ad5df43dd61e7f1b24a12 +3798e5de334c3deb5f71302b782f6b8fbd5087f1 +326ffed09bfcc209a2efd6a2ebc69edf6bd200b5 +97d83739db0631be5d4ba86af3616014652c00ec diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh index c21febb9e9..1f14635f61 100755 --- a/contrib/verify-commits/pre-push-hook.sh +++ b/contrib/verify-commits/pre-push-hook.sh @@ -12,9 +12,9 @@ while read LINE; do if [ "$4" != "refs/heads/master" ]; then continue fi - if ! ./contrib/verify-commits/verify-commits.sh $3 > /dev/null 2>&1; then + if ! ./contrib/verify-commits/verify-commits.py $3 > /dev/null 2>&1; then echo "ERROR: A commit is not signed, can't push" - ./contrib/verify-commits/verify-commits.sh + ./contrib/verify-commits/verify-commits.py exit 1 fi done < /dev/stdin diff --git a/contrib/verify-commits/verify-commits.py b/contrib/verify-commits/verify-commits.py new file mode 100755 index 0000000000..80f0aa0bf1 --- /dev/null +++ b/contrib/verify-commits/verify-commits.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +# 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. +"""Verify commits against a trusted keys list.""" +import argparse +import hashlib +import os +import subprocess +import sys +import time + +GIT = os.getenv('GIT', 'git') + +def tree_sha512sum(commit='HEAD'): + """Calculate the Tree-sha512 for the commit. + + This is copied from github-merge.py.""" + + # request metadata for entire tree, recursively + files = [] + blob_by_name = {} + for line in subprocess.check_output([GIT, 'ls-tree', '--full-tree', '-r', commit]).splitlines(): + name_sep = line.index(b'\t') + metadata = line[:name_sep].split() # perms, 'blob', blobid + assert metadata[1] == b'blob' + name = line[name_sep + 1:] + files.append(name) + blob_by_name[name] = metadata[2] + + files.sort() + # open connection to git-cat-file in batch mode to request data for all blobs + # this is much faster than launching it per file + p = subprocess.Popen([GIT, 'cat-file', '--batch'], stdout=subprocess.PIPE, stdin=subprocess.PIPE) + overall = hashlib.sha512() + for f in files: + blob = blob_by_name[f] + # request blob + p.stdin.write(blob + b'\n') + p.stdin.flush() + # read header: blob, "blob", size + reply = p.stdout.readline().split() + assert reply[0] == blob and reply[1] == b'blob' + size = int(reply[2]) + # hash the blob data + intern = hashlib.sha512() + ptr = 0 + while ptr < size: + bs = min(65536, size - ptr) + piece = p.stdout.read(bs) + if len(piece) == bs: + intern.update(piece) + else: + raise IOError('Premature EOF reading git cat-file output') + ptr += bs + dig = intern.hexdigest() + assert p.stdout.read(1) == b'\n' # ignore LF that follows blob data + # update overall hash with file hash + overall.update(dig.encode("utf-8")) + overall.update(" ".encode("utf-8")) + overall.update(f) + overall.update("\n".encode("utf-8")) + p.stdin.close() + if p.wait(): + raise IOError('Non-zero return value executing git cat-file') + return overall.hexdigest() + +def main(): + # Parse arguments + parser = argparse.ArgumentParser(usage='%(prog)s [options] [commit id]') + parser.add_argument('--disable-tree-check', action='store_false', dest='verify_tree', help='disable SHA-512 tree check') + parser.add_argument('--clean-merge', type=float, dest='clean_merge', default=float('inf'), help='Only check clean merge after <NUMBER> days ago (default: %(default)s)', metavar='NUMBER') + parser.add_argument('commit', nargs='?', default='HEAD', help='Check clean merge up to commit <commit>') + args = parser.parse_args() + + # get directory of this program and read data files + dirname = os.path.dirname(os.path.abspath(__file__)) + print("Using verify-commits data from " + dirname) + verified_root = open(dirname + "/trusted-git-root", "r").read().splitlines()[0] + verified_sha512_root = open(dirname + "/trusted-sha512-root-commit", "r").read().splitlines()[0] + revsig_allowed = open(dirname + "/allow-revsig-commits", "r").read().splitlines() + unclean_merge_allowed = open(dirname + "/allow-unclean-merge-commits", "r").read().splitlines() + incorrect_sha512_allowed = open(dirname + "/allow-incorrect-sha512-commits", "r").read().splitlines() + + # Set commit and branch and set variables + current_commit = args.commit + if ' ' in current_commit: + print("Commit must not contain spaces", file=sys.stderr) + sys.exit(1) + verify_tree = args.verify_tree + no_sha1 = True + prev_commit = "" + initial_commit = current_commit + branch = subprocess.check_output([GIT, 'show', '-s', '--format=%H', initial_commit], universal_newlines=True).splitlines()[0] + + # Iterate through commits + while True: + if current_commit == verified_root: + print('There is a valid path from "{}" to {} where all commits are signed!'.format(initial_commit, verified_root)) + sys.exit(0) + if current_commit == verified_sha512_root: + if verify_tree: + print("All Tree-SHA512s matched up to {}".format(verified_sha512_root), file=sys.stderr) + verify_tree = False + no_sha1 = False + + os.environ['BITCOIN_VERIFY_COMMITS_ALLOW_SHA1'] = "0" if no_sha1 else "1" + os.environ['BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG'] = "1" if current_commit in revsig_allowed else "0" + + # Check that the commit (and parents) was signed with a trusted key + if subprocess.call([GIT, '-c', 'gpg.program={}/gpg.sh'.format(dirname), 'verify-commit', current_commit], stdout=subprocess.DEVNULL): + if prev_commit != "": + print("No parent of {} was signed with a trusted key!".format(prev_commit), file=sys.stderr) + print("Parents are:", file=sys.stderr) + parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', prev_commit], universal_newlines=True).splitlines()[0].split(' ') + for parent in parents: + subprocess.call([GIT, 'show', '-s', parent], stdout=sys.stderr) + else: + print("{} was not signed with a trusted key!".format(current_commit), file=sys.stderr) + sys.exit(1) + + # Check the Tree-SHA512 + if (verify_tree or prev_commit == "") and current_commit not in incorrect_sha512_allowed: + tree_hash = tree_sha512sum(current_commit) + if ("Tree-SHA512: {}".format(tree_hash)) not in subprocess.check_output([GIT, 'show', '-s', '--format=format:%B', current_commit], universal_newlines=True).splitlines(): + print("Tree-SHA512 did not match for commit " + current_commit, file=sys.stderr) + sys.exit(1) + + # Merge commits should only have two parents + parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', current_commit], universal_newlines=True).splitlines()[0].split(' ') + if len(parents) > 2: + print("Commit {} is an octopus merge".format(current_commit), file=sys.stderr) + sys.exit(1) + + # Check that the merge commit is clean + commit_time = int(subprocess.check_output([GIT, 'show', '-s', '--format=format:%ct', current_commit], universal_newlines=True).splitlines()[0]) + check_merge = commit_time > time.time() - args.clean_merge * 24 * 60 * 60 # Only check commits in clean_merge days + allow_unclean = current_commit in unclean_merge_allowed + if len(parents) == 2 and check_merge and not allow_unclean: + current_tree = subprocess.check_output([GIT, 'show', '--format=%T', current_commit], universal_newlines=True).splitlines()[0] + subprocess.call([GIT, 'checkout', '--force', '--quiet', parents[0]]) + subprocess.call([GIT, 'merge', '--no-ff', '--quiet', parents[1]], stdout=subprocess.DEVNULL) + recreated_tree = subprocess.check_output([GIT, 'show', '--format=format:%T', 'HEAD'], universal_newlines=True).splitlines()[0] + if current_tree != recreated_tree: + print("Merge commit {} is not clean".format(current_commit), file=sys.stderr) + subprocess.call([GIT, 'diff', current_commit]) + subprocess.call([GIT, 'checkout', '--force', '--quiet', branch]) + sys.exit(1) + subprocess.call([GIT, 'checkout', '--force', '--quiet', branch]) + + prev_commit = current_commit + current_commit = parents[0] + +if __name__ == '__main__': + main() diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh deleted file mode 100755 index 6415eea4d5..0000000000 --- a/contrib/verify-commits/verify-commits.sh +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/sh -# Copyright (c) 2014-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. - -DIR=$(dirname "$0") -[ "/${DIR#/}" != "$DIR" ] && DIR=$(dirname "$(pwd)/$0") - -echo "Using verify-commits data from ${DIR}" - -VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") -VERIFIED_SHA512_ROOT=$(cat "${DIR}/trusted-sha512-root-commit") -REVSIG_ALLOWED=$(cat "${DIR}/allow-revsig-commits") - -HAVE_GNU_SHA512=1 -[ ! -x "$(which sha512sum)" ] && HAVE_GNU_SHA512=0 - -if [ x"$1" = "x" ]; then - CURRENT_COMMIT="HEAD" -else - CURRENT_COMMIT="$1" -fi - -if [ "${CURRENT_COMMIT#* }" != "$CURRENT_COMMIT" ]; then - echo "Commit must not contain spaces?" > /dev/stderr - exit 1 -fi - -VERIFY_TREE=0 -if [ x"$2" = "x--tree-checks" ]; then - VERIFY_TREE=1 -fi - -NO_SHA1=1 -PREV_COMMIT="" -INITIAL_COMMIT="${CURRENT_COMMIT}" - -BRANCH="$(git rev-parse --abbrev-ref HEAD)" - -while true; do - if [ "$CURRENT_COMMIT" = $VERIFIED_ROOT ]; then - echo "There is a valid path from \"$INITIAL_COMMIT\" to $VERIFIED_ROOT where all commits are signed!" - exit 0 - fi - - if [ "$CURRENT_COMMIT" = $VERIFIED_SHA512_ROOT ]; then - if [ "$VERIFY_TREE" = "1" ]; then - echo "All Tree-SHA512s matched up to $VERIFIED_SHA512_ROOT" > /dev/stderr - fi - VERIFY_TREE=0 - NO_SHA1=0 - fi - - if [ "$NO_SHA1" = "1" ]; then - export BITCOIN_VERIFY_COMMITS_ALLOW_SHA1=0 - else - export BITCOIN_VERIFY_COMMITS_ALLOW_SHA1=1 - fi - - if [ "${REVSIG_ALLOWED#*$CURRENT_COMMIT}" != "$REVSIG_ALLOWED" ]; then - export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1 - else - export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0 - fi - - if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit "$CURRENT_COMMIT" > /dev/null; then - if [ "$PREV_COMMIT" != "" ]; then - echo "No parent of $PREV_COMMIT was signed with a trusted key!" > /dev/stderr - echo "Parents are:" > /dev/stderr - PARENTS=$(git show -s --format=format:%P $PREV_COMMIT) - for PARENT in $PARENTS; do - git show -s $PARENT > /dev/stderr - done - else - echo "$CURRENT_COMMIT was not signed with a trusted key!" > /dev/stderr - fi - exit 1 - fi - - # We always verify the top of the tree - if [ "$VERIFY_TREE" = 1 -o "$PREV_COMMIT" = "" ]; then - IFS_CACHE="$IFS" - IFS=' -' - for LINE in $(git ls-tree --full-tree -r "$CURRENT_COMMIT"); do - case "$LINE" in - "12"*) - echo "Repo contains symlinks" > /dev/stderr - IFS="$IFS_CACHE" - exit 1 - ;; - esac - done - IFS="$IFS_CACHE" - - FILE_HASHES="" - for FILE in $(git ls-tree --full-tree -r --name-only "$CURRENT_COMMIT" | LC_ALL=C sort); do - if [ "$HAVE_GNU_SHA512" = 1 ]; then - HASH=$(git cat-file blob "$CURRENT_COMMIT":"$FILE" | sha512sum | { read FIRST _; echo $FIRST; } ) - else - HASH=$(git cat-file blob "$CURRENT_COMMIT":"$FILE" | shasum -a 512 | { read FIRST _; echo $FIRST; } ) - fi - [ "$FILE_HASHES" != "" ] && FILE_HASHES="$FILE_HASHES"' -' - FILE_HASHES="$FILE_HASHES$HASH $FILE" - done - - if [ "$HAVE_GNU_SHA512" = 1 ]; then - TREE_HASH="$(echo "$FILE_HASHES" | sha512sum)" - else - TREE_HASH="$(echo "$FILE_HASHES" | shasum -a 512)" - fi - HASH_MATCHES=0 - MSG="$(git show -s --format=format:%B "$CURRENT_COMMIT" | tail -n1)" - - case "$MSG -" in - "Tree-SHA512: $TREE_HASH") - HASH_MATCHES=1;; - esac - - if [ "$HASH_MATCHES" = "0" ]; then - echo "Tree-SHA512 did not match for commit $CURRENT_COMMIT" > /dev/stderr - exit 1 - fi - fi - - PARENTS=$(git show -s --format=format:%P "$CURRENT_COMMIT") - PARENT1=${PARENTS%% *} - PARENT2="" - if [ "x$PARENT1" != "x$PARENTS" ]; then - PARENTX=${PARENTS#* } - PARENT2=${PARENTX%% *} - if [ "x$PARENT2" != "x$PARENTX" ]; then - echo "Commit $CURRENT_COMMIT is an octopus merge" > /dev/stderr - exit 1 - fi - fi - if [ "x$PARENT2" != "x" ]; then - CURRENT_TREE="$(git show --format="%T" "$CURRENT_COMMIT")" - git checkout --force --quiet "$PARENT1" - git merge --no-ff --quiet "$PARENT2" >/dev/null - RECREATED_TREE="$(git show --format="%T" HEAD)" - if [ "$CURRENT_TREE" != "$RECREATED_TREE" ]; then - echo "Merge commit $CURRENT_COMMIT is not clean" > /dev/stderr - git diff "$CURRENT_COMMIT" - git checkout --force --quiet "$BRANCH" - exit 1 - fi - git checkout --force --quiet "$BRANCH" - fi - PREV_COMMIT="$CURRENT_COMMIT" - CURRENT_COMMIT="$PARENT1" -done |