mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-04-10 07:37:59 +02:00
Merge bitcoin/bitcoin#34439: qa: Drop recursive deletes from test code, add lint checks.
0d1301b47atest: functional: drop rmtree usage and add lint check (David Gumberg)8bfb422de8test: functional: drop unused --keepcache argument (David Gumberg)a7e4a59d6dqa: Remove all instances of `remove_all` except test cleanup (David Gumberg) Pull request description: Both `fs::remove_all` and `shutil::rmtree()` are a bit dangerous, and most of their uses are not necessary, this PR removes most instances of both. `remove_all()` is still used in in `src/test/util/setup_common.cpp` as part of `BasicTestingSetup::BasicTestingSetup`'s constructor and destructor, and it is used in the kernel test code's [`TestDirectory`](4ae00e9a71/src/test/kernel/test_kernel.cpp (L100-L112)):734899a4c4/src/test/kernel/test_kernel.cpp (L100-L112)In both cases, `remove_all` is likely necessary, but the kernel's test code is RAII, ideally `BasicTestingSetup` could be made similar in a follow-up or in this PR if reviewers think it is important. Similarly in the python code, most usage was unnecessary, but there are a few places where `rmtree()` was necessary, I have added sanity checks to make sure these are inside of the `tmpdir` before doing recursive delete there. ACKs for top commit: achow101: ACK0d1301b47ahodlinator: ACK0d1301b47asedited: ACK0d1301b47aTree-SHA512: da8ca23846b73eff0eaff61a5f80ba1decf63db783dcd86b25f88f4862ae28816fc9e2e9ee71283ec800d73097b1cfae64e3c5ba0e991be69c200c6098f24d6e
This commit is contained in:
@@ -44,16 +44,19 @@ static void WalletCreate(benchmark::Bench& bench, bool encrypted)
|
||||
bilingual_str error_string;
|
||||
std::vector<bilingual_str> warnings;
|
||||
|
||||
auto wallet_path = fs::PathToString(test_setup->m_path_root / "test_wallet");
|
||||
const auto wallet_path = test_setup->m_path_root / "test_wallet";
|
||||
const auto wallet_name = fs::PathToString(wallet_path);
|
||||
|
||||
bench.run([&] {
|
||||
auto wallet = CreateWallet(context, wallet_path, /*load_on_start=*/std::nullopt, options, status, error_string, warnings);
|
||||
auto wallet = CreateWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error_string, warnings);
|
||||
assert(status == DatabaseStatus::SUCCESS);
|
||||
assert(wallet != nullptr);
|
||||
|
||||
// Release wallet
|
||||
RemoveWallet(context, wallet, /*load_on_start=*/ std::nullopt);
|
||||
WaitForDeleteWallet(std::move(wallet));
|
||||
fs::remove_all(wallet_path);
|
||||
fs::remove(wallet_path / "wallet.dat");
|
||||
fs::remove(wallet_path);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ FUZZ_TARGET(i2p, .init = initialize_i2p)
|
||||
}
|
||||
}
|
||||
|
||||
fs::remove_all(private_key_path);
|
||||
fs::remove(private_key_path);
|
||||
|
||||
CreateSock = CreateSockOrig;
|
||||
}
|
||||
|
||||
@@ -1175,8 +1175,8 @@ BOOST_AUTO_TEST_CASE(btck_chainman_regtest_tests)
|
||||
BOOST_CHECK_EQUAL(count, chain.CountEntries());
|
||||
|
||||
|
||||
fs::remove_all(test_directory.m_directory / "blocks" / "blk00000.dat");
|
||||
fs::remove(test_directory.m_directory / "blocks" / "blk00000.dat");
|
||||
BOOST_CHECK(!chainman->ReadBlock(tip_2).has_value());
|
||||
fs::remove_all(test_directory.m_directory / "blocks" / "rev00000.dat");
|
||||
fs::remove(test_directory.m_directory / "blocks" / "rev00000.dat");
|
||||
BOOST_CHECK_THROW(chainman->ReadBlockSpentOutputs(tip), std::runtime_error);
|
||||
}
|
||||
|
||||
@@ -1138,7 +1138,8 @@ BOOST_AUTO_TEST_CASE(test_LockDirectory)
|
||||
#endif
|
||||
// Clean up
|
||||
ReleaseDirectoryLocks();
|
||||
fs::remove_all(dirname);
|
||||
fs::remove(dirname / lockname);
|
||||
fs::remove(dirname);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ToLower)
|
||||
|
||||
@@ -10,7 +10,6 @@ The assumeutxo value generated and used here is committed to in
|
||||
`CRegTestParams::m_assumeutxo_data` in `src/kernel/chainparams.cpp`.
|
||||
"""
|
||||
import contextlib
|
||||
from shutil import rmtree
|
||||
|
||||
from dataclasses import dataclass
|
||||
from test_framework.blocktools import (
|
||||
@@ -192,7 +191,8 @@ class AssumeutxoTest(BitcoinTestFramework):
|
||||
expected_error(log_msg=error_details, error_msg=expected_error_msg)
|
||||
|
||||
# resurrect node again
|
||||
rmtree(chainstate_snapshot_path)
|
||||
(chainstate_snapshot_path / "base_blockhash").unlink()
|
||||
chainstate_snapshot_path.rmdir()
|
||||
self.start_node(0)
|
||||
|
||||
def test_invalid_mempool_state(self, dump_output_path):
|
||||
@@ -304,7 +304,7 @@ class AssumeutxoTest(BitcoinTestFramework):
|
||||
# Start test fresh by cleaning up node directories
|
||||
for node in (snapshot_node, ibd_node):
|
||||
self.stop_node(node.index)
|
||||
rmtree(node.chain_path)
|
||||
self.cleanup_folder(node.chain_path)
|
||||
self.start_node(node.index, extra_args=self.extra_args[node.index])
|
||||
|
||||
# Sync-up headers chain on snapshot_node to load snapshot
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"""Test the blocksdir option.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework, initialize_datadir
|
||||
@@ -20,7 +19,7 @@ class BlocksdirTest(BitcoinTestFramework):
|
||||
self.stop_node(0)
|
||||
assert self.nodes[0].blocks_path.is_dir()
|
||||
assert not (self.nodes[0].datadir_path / "blocks").is_dir()
|
||||
shutil.rmtree(self.nodes[0].datadir_path)
|
||||
self.cleanup_folder(self.nodes[0].datadir_path)
|
||||
initialize_datadir(self.options.tmpdir, 0, self.chain)
|
||||
self.log.info("Starting with nonexistent blocksdir ...")
|
||||
blocksdir_path = Path(self.options.tmpdir) / 'blocksdir'
|
||||
|
||||
@@ -49,7 +49,7 @@ class CoinStatsIndexTest(BitcoinTestFramework):
|
||||
|
||||
self.log.info("Test that gettxoutsetinfo() output is consistent for the new index running on a datadir with the old version")
|
||||
self.stop_nodes()
|
||||
shutil.rmtree(node.chain_path / "indexes" / "coinstatsindex")
|
||||
self.cleanup_folder(node.chain_path / "indexes" / "coinstatsindex")
|
||||
shutil.copytree(legacy_node.chain_path / "indexes" / "coinstats", node.chain_path / "indexes" / "coinstats")
|
||||
old_version_path = node.chain_path / "indexes" / "coinstats"
|
||||
msg = f'[warning] Old version of coinstatsindex found at {old_version_path}. This folder can be safely deleted unless you plan to downgrade your node to version 29 or lower.'
|
||||
|
||||
@@ -241,7 +241,7 @@ class InitTest(BitcoinTestFramework):
|
||||
start_expecting_error(err_fragment, startup_args)
|
||||
|
||||
for dir in dirs:
|
||||
shutil.rmtree(node.chain_path / dir)
|
||||
self.cleanup_folder(node.chain_path / dir)
|
||||
shutil.move(node.chain_path / f"{dir}_bak", node.chain_path / dir)
|
||||
|
||||
def init_pid_test(self):
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
||||
class ReindexInitTest(BitcoinTestFramework):
|
||||
@@ -19,7 +18,7 @@ class ReindexInitTest(BitcoinTestFramework):
|
||||
self.stop_nodes()
|
||||
|
||||
self.log.info("Removing the block index leads to init error")
|
||||
shutil.rmtree(node.blocks_path / "index")
|
||||
self.cleanup_folder(node.blocks_path / "index")
|
||||
node.assert_start_raises_init_error(
|
||||
expected_msg=f"Error initializing block database.{os.linesep}"
|
||||
"Please restart with -reindex or -reindex-chainstate to recover.",
|
||||
|
||||
@@ -10,6 +10,7 @@ import argparse
|
||||
from datetime import datetime, timezone
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import pdb
|
||||
import random
|
||||
@@ -331,7 +332,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
h.flush()
|
||||
rpc_logger.removeHandler(h)
|
||||
if cleanup_tree_on_exit:
|
||||
shutil.rmtree(self.options.tmpdir)
|
||||
self.cleanup_folder(self.options.tmpdir)
|
||||
|
||||
self.nodes.clear()
|
||||
return exit_code
|
||||
@@ -1031,3 +1032,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
||||
return result
|
||||
except ImportError:
|
||||
self.log.warning("sqlite3 module not available, skipping tests that inspect the database")
|
||||
|
||||
def cleanup_folder(self, _path):
|
||||
path = Path(_path)
|
||||
if not path.is_relative_to(self.options.tmpdir):
|
||||
raise AssertionError(f"Trying to delete #{path} outside of #{self.options.tmpdir}")
|
||||
shutil.rmtree(path)
|
||||
|
||||
@@ -11,7 +11,6 @@ from enum import Enum
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
@@ -20,7 +19,6 @@ import time
|
||||
import urllib.parse
|
||||
import collections
|
||||
import shlex
|
||||
import shutil
|
||||
import sys
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
@@ -163,8 +161,8 @@ class TestNode():
|
||||
self.args.append("-ipcbind=unix")
|
||||
else:
|
||||
# Work around default CI path exceeding maximum socket path length.
|
||||
self.ipc_tmp_dir = pathlib.Path(tempfile.mkdtemp(prefix="test-ipc-"))
|
||||
self.ipc_socket_path = self.ipc_tmp_dir / "node.sock"
|
||||
self.ipc_tmp_dir = tempfile.TemporaryDirectory(prefix="test-ipc-")
|
||||
self.ipc_socket_path = Path(self.ipc_tmp_dir.name) / "node.sock"
|
||||
self.args.append(f"-ipcbind=unix:{self.ipc_socket_path}")
|
||||
|
||||
if self.version_is_at_least(190000):
|
||||
@@ -248,9 +246,6 @@ class TestNode():
|
||||
# this destructor is called.
|
||||
print(self._node_msg("Cleaning up leftover process"), file=sys.stderr)
|
||||
self.process.kill()
|
||||
if self.ipc_tmp_dir:
|
||||
print(self._node_msg(f"Cleaning up ipc directory {str(self.ipc_tmp_dir)!r}"))
|
||||
shutil.rmtree(self.ipc_tmp_dir)
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
|
||||
|
||||
@@ -415,7 +415,6 @@ def main():
|
||||
parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests')
|
||||
parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit')
|
||||
parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.')
|
||||
parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.')
|
||||
parser.add_argument('--quiet', '-q', action='store_true', help='only print dots, results summary and failure logs')
|
||||
parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs")
|
||||
parser.add_argument('--failfast', '-F', action='store_true', help='stop execution after the first test failure')
|
||||
@@ -565,9 +564,6 @@ def main():
|
||||
check_script_list(src_dir=config["environment"]["SRCDIR"], fail_on_warn=fail_on_warn)
|
||||
check_script_prefixes()
|
||||
|
||||
if not args.keepcache:
|
||||
shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True)
|
||||
|
||||
run_tests(
|
||||
test_list=test_list,
|
||||
build_dir=config["environment"]["BUILDDIR"],
|
||||
@@ -598,11 +594,6 @@ def run_tests(*, test_list, build_dir, tmpdir, jobs=1, enable_coverage=False, ar
|
||||
# pgrep not supported
|
||||
pass
|
||||
|
||||
# Warn if there is a cache directory
|
||||
cache_dir = "%s/test/cache" % build_dir
|
||||
if os.path.isdir(cache_dir):
|
||||
print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir))
|
||||
|
||||
# Warn if there is not enough space on the testing dir
|
||||
min_space = MIN_FREE_SPACE + (jobs - 1) * ADDITIONAL_SPACE_PER_JOB
|
||||
if shutil.disk_usage(tmpdir).free < min_space:
|
||||
@@ -614,7 +605,8 @@ def run_tests(*, test_list, build_dir, tmpdir, jobs=1, enable_coverage=False, ar
|
||||
# a hard link or a copy on any platform. See https://github.com/bitcoin/bitcoin/pull/27561.
|
||||
sys.path.append(tests_dir)
|
||||
|
||||
flags = ['--cachedir={}'.format(cache_dir)] + args
|
||||
cache_tmp_dir = tempfile.TemporaryDirectory(prefix="functional_test_cache")
|
||||
flags = [f"--cachedir={cache_tmp_dir.name}"] + args
|
||||
|
||||
if enable_coverage:
|
||||
coverage = RPCCoverage()
|
||||
@@ -631,7 +623,7 @@ def run_tests(*, test_list, build_dir, tmpdir, jobs=1, enable_coverage=False, ar
|
||||
sys.stdout.buffer.write(e.output)
|
||||
raise
|
||||
|
||||
#Run Tests
|
||||
# Run Tests
|
||||
job_queue = TestHandler(
|
||||
num_tests_parallel=jobs,
|
||||
tests_dir=tests_dir,
|
||||
@@ -689,9 +681,6 @@ def run_tests(*, test_list, build_dir, tmpdir, jobs=1, enable_coverage=False, ar
|
||||
|
||||
if coverage:
|
||||
coverage_passed = coverage.report_rpc_coverage()
|
||||
|
||||
logging.debug("Cleaning up coverage data")
|
||||
coverage.cleanup()
|
||||
else:
|
||||
coverage_passed = True
|
||||
|
||||
@@ -906,7 +895,8 @@ class RPCCoverage():
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.dir = tempfile.mkdtemp(prefix="coverage")
|
||||
self.temp_dir = tempfile.TemporaryDirectory(prefix="coverage")
|
||||
self.dir = self.temp_dir.name
|
||||
self.flag = '--coveragedir=%s' % self.dir
|
||||
|
||||
def report_rpc_coverage(self):
|
||||
@@ -924,9 +914,6 @@ class RPCCoverage():
|
||||
print("All RPC commands covered.")
|
||||
return True
|
||||
|
||||
def cleanup(self):
|
||||
return shutil.rmtree(self.dir)
|
||||
|
||||
def _get_uncovered_rpc_commands(self):
|
||||
"""
|
||||
Return a set of currently untested RPC commands.
|
||||
|
||||
@@ -303,7 +303,8 @@ class BackwardsCompatibilityTest(BitcoinTestFramework):
|
||||
# Copy back to master
|
||||
wallet.unloadwallet()
|
||||
if n == node:
|
||||
shutil.rmtree(node_master.wallets_path / wallet_name)
|
||||
(node_master.wallets_path / wallet_name / "wallet.dat").unlink()
|
||||
(node_master.wallets_path / wallet_name).rmdir()
|
||||
shutil.copytree(
|
||||
n.wallets_path / wallet_name,
|
||||
node_master.wallets_path / wallet_name,
|
||||
|
||||
@@ -70,8 +70,8 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
self.stop_node(1)
|
||||
# we need to delete the complete chain directory
|
||||
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
|
||||
shutil.rmtree(self.nodes[1].blocks_path)
|
||||
shutil.rmtree(self.nodes[1].chain_path / "chainstate")
|
||||
self.cleanup_folder(self.nodes[1].blocks_path)
|
||||
self.cleanup_folder(self.nodes[1].chain_path / "chainstate")
|
||||
shutil.copyfile(
|
||||
self.nodes[1].datadir_path / "hd.bak",
|
||||
self.nodes[1].wallets_path / self.default_wallet_name / self.wallet_data_filename
|
||||
@@ -95,8 +95,8 @@ class WalletHDTest(BitcoinTestFramework):
|
||||
|
||||
# Try a RPC based rescan
|
||||
self.stop_node(1)
|
||||
shutil.rmtree(self.nodes[1].blocks_path)
|
||||
shutil.rmtree(self.nodes[1].chain_path / "chainstate")
|
||||
self.cleanup_folder(self.nodes[1].blocks_path)
|
||||
self.cleanup_folder(self.nodes[1].chain_path / "chainstate")
|
||||
shutil.copyfile(
|
||||
self.nodes[1].datadir_path / "hd.bak",
|
||||
self.nodes[1].wallets_path / self.default_wallet_name / self.wallet_data_filename
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test Migrating a wallet from legacy to descriptor."""
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
import os.path
|
||||
import random
|
||||
@@ -664,8 +665,12 @@ class WalletMigrationTest(BitcoinTestFramework):
|
||||
# Test cleanup: Clear unnamed default wallet for subsequent tests
|
||||
(self.old_node.wallets_path / "wallet.dat").unlink()
|
||||
(self.master_node.wallets_path / "wallet.dat").unlink(missing_ok=True)
|
||||
shutil.rmtree(self.master_node.wallets_path / "default_wallet_watchonly", ignore_errors=True)
|
||||
shutil.rmtree(self.master_node.wallets_path / "default_wallet_solvables", ignore_errors=True)
|
||||
with suppress(FileNotFoundError):
|
||||
(self.master_node.wallets_path / "default_wallet_watchonly" / "wallet.dat").unlink()
|
||||
(self.master_node.wallets_path / "default_wallet_watchonly").rmdir()
|
||||
|
||||
(self.master_node.wallets_path / "default_wallet_solvables" / "wallet.dat").unlink()
|
||||
(self.master_node.wallets_path / "default_wallet_solvables").rmdir()
|
||||
backup_file.unlink()
|
||||
|
||||
def test_default_wallet(self):
|
||||
|
||||
@@ -140,12 +140,12 @@ class MultiWalletTest(BitcoinTestFramework):
|
||||
self.stop_nodes()
|
||||
empty_wallet = os.path.join(self.options.tmpdir, 'empty.dat')
|
||||
os.rename(self.wallet_file(node, "empty"), empty_wallet)
|
||||
shutil.rmtree(wallet_dir(node, "empty"))
|
||||
os.rmdir(wallet_dir(node, "empty"))
|
||||
empty_created_wallet = os.path.join(self.options.tmpdir, 'empty.created.dat')
|
||||
os.rename(wallet_dir(node, "created", self.wallet_data_filename), empty_created_wallet)
|
||||
shutil.rmtree(wallet_dir(node, "created"))
|
||||
os.rmdir(wallet_dir(node, "created"))
|
||||
os.rename(self.wallet_file(node, "plain"), wallet_dir(node, "w8"))
|
||||
shutil.rmtree(wallet_dir(node, "plain"))
|
||||
os.rmdir(wallet_dir(node, "plain"))
|
||||
|
||||
# restart node with a mix of wallet names:
|
||||
# w1, w2, w3 - to verify new wallets created when non-existing paths specified
|
||||
|
||||
@@ -72,7 +72,7 @@ class ReorgsRestoreTest(BitcoinTestFramework):
|
||||
# Stop both nodes and replace node0 chain entirely for the node1 chain
|
||||
self.stop_nodes()
|
||||
for path in ["chainstate", "blocks"]:
|
||||
shutil.rmtree(self.nodes[0].chain_path / path)
|
||||
self.cleanup_folder(self.nodes[0].chain_path / path)
|
||||
shutil.copytree(self.nodes[1].chain_path / path, self.nodes[0].chain_path / path)
|
||||
|
||||
# Start node0 and verify that now it has node1 chain and no info about its previous best block
|
||||
|
||||
@@ -36,7 +36,7 @@ class WalletStartupTest(BitcoinTestFramework):
|
||||
self.nodes[0].createwallet(wallet_name=wallet_name, **kwargs)
|
||||
self.nodes[0].unloadwallet(wallet_name)
|
||||
shutil.move(self.nodes[0].wallets_path / wallet_name / "wallet.dat", self.nodes[0].wallets_path / "wallet.dat")
|
||||
shutil.rmtree(self.nodes[0].wallets_path / wallet_name)
|
||||
(self.nodes[0].wallets_path / wallet_name).rmdir()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info('Should start without any wallets')
|
||||
|
||||
@@ -122,6 +122,32 @@ fs:: namespace, which has unsafe filesystem functions marked as deleted.
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lint_remove_all() -> LintResult {
|
||||
let found = git()
|
||||
.args([
|
||||
"grep",
|
||||
"--line-number",
|
||||
"remove_all(.*)",
|
||||
"--",
|
||||
"./src/",
|
||||
// These are likely not avoidable.
|
||||
":(exclude)src/test/kernel/test_kernel.cpp",
|
||||
":(exclude)src/test/util/setup_common.cpp",
|
||||
])
|
||||
.status()
|
||||
.expect("command error")
|
||||
.success();
|
||||
if found {
|
||||
Err(r#"
|
||||
Use of fs::remove_all or std::filesystem::remove_all is dangerous and should be avoided.
|
||||
"#
|
||||
.trim()
|
||||
.to_string())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lint_rpc_assert() -> LintResult {
|
||||
let found = git()
|
||||
.args([
|
||||
|
||||
@@ -73,3 +73,28 @@ pub fn lint_py_lint() -> LintResult {
|
||||
Err(e) => Err(format!("Error running `{bin_name}`: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lint_rmtree() -> LintResult {
|
||||
let found = git()
|
||||
.args([
|
||||
"grep",
|
||||
"--line-number",
|
||||
"rmtree",
|
||||
"--",
|
||||
"test/functional/",
|
||||
":(exclude)test/functional/test_framework/test_framework.py",
|
||||
])
|
||||
.status()
|
||||
.expect("command error")
|
||||
.success();
|
||||
if found {
|
||||
Err(r#"
|
||||
Use of shutil.rmtree() is dangerous and should be avoided.
|
||||
"#
|
||||
.trim()
|
||||
.to_string())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ use std::fs;
|
||||
use std::process::{Command, ExitCode};
|
||||
|
||||
use lint_cpp::{
|
||||
lint_boost_assert, lint_includes_build_config, lint_rpc_assert, lint_std_filesystem,
|
||||
lint_boost_assert, lint_includes_build_config, lint_remove_all, lint_rpc_assert, lint_std_filesystem,
|
||||
};
|
||||
use lint_docs::{lint_doc_args, lint_doc_release_note_snippets, lint_markdown};
|
||||
use lint_py::lint_py_lint;
|
||||
use lint_py::{lint_py_lint, lint_rmtree};
|
||||
use lint_repo_hygiene::{lint_scripted_diff, lint_subtree};
|
||||
use lint_text_format::{
|
||||
lint_commit_msg, lint_tabs_whitespace, lint_trailing_newline, lint_trailing_whitespace,
|
||||
@@ -52,11 +52,21 @@ fn get_linter_list() -> Vec<&'static Linter> {
|
||||
name: "py_lint",
|
||||
lint_fn: lint_py_lint,
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that shutil.rmtree is not used",
|
||||
name: "rmtree",
|
||||
lint_fn: lint_rmtree,
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that std::filesystem is not used directly",
|
||||
name: "std_filesystem",
|
||||
lint_fn: lint_std_filesystem
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that remove_all is not used",
|
||||
name: "remove_all",
|
||||
lint_fn: lint_remove_all
|
||||
},
|
||||
&Linter {
|
||||
description: "Check that fatal assertions are not used in RPC code",
|
||||
name: "rpc_assert",
|
||||
|
||||
Reference in New Issue
Block a user