summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorBinbin <binloveplay1314@qq.com>2022-05-27 17:58:00 +0800
committerGitHub <noreply@github.com>2022-05-27 12:58:00 +0300
commit2a099d49d457239201b38c3ec97054a167658b6e (patch)
treedf5a74aff673143a9c093db5e9f06b778a4bb910 /utils
parent6f7c1a8ce6861fb382f8313d07a6e2a13217a690 (diff)
downloadredis-2a099d49d457239201b38c3ec97054a167658b6e.tar.gz
Fix some commands key spec in json files (#10779)
There are some commands that has the wrong key specs. This PR adds a key-spec related check in generate-command-code.py. Check if the index is valid, or if there is an unused index. The check result will look like: ``` [root]# python utils/generate-command-code.py Processing json files... Linking container command to subcommands... Checking all commands... command: RESTORE_ASKING may have unused key_spec command: RENAME may have unused key_spec command: PFDEBUG may have unused key_spec command: WATCH key_specs missing flags command: LCS arg: key2 key_spec_index error command: RENAMENX may have unused key_spec Error: There are errors in the commands check, please check the above logs. ``` The following commands have been fixed according to the check results: - RESTORE ASKING: add missing arguments section (and history section) - RENAME: newkey's key_spec_index should be 1 - PFDEBUG: add missing arguments (and change the arity from -3 to 3) - WATCH: add missing key_specs flags: RO, like EXIST (it allow you to know the key exists, or is modified, but doesn't "leak" the data) - LCS: key2 key_spec_index error, there is only one key-spec - RENAMENX: newkey's key_spec_index should be 1
Diffstat (limited to 'utils')
-rwxr-xr-xutils/generate-command-code.py67
-rwxr-xr-xutils/generate-commands-json.py7
2 files changed, 68 insertions, 6 deletions
diff --git a/utils/generate-command-code.py b/utils/generate-command-code.py
index c5c08e196..605bde40f 100755
--- a/utils/generate-command-code.py
+++ b/utils/generate-command-code.py
@@ -1,8 +1,7 @@
#!/usr/bin/env python3
-
-import os
import glob
import json
+import os
ARG_TYPES = {
"string": "ARG_TYPE_STRING",
@@ -68,6 +67,55 @@ def get_optional_desc_string(desc, field, force_uppercase=False):
return ret.replace("\n", "\\n")
+def check_command_args_key_specs(args, command_key_specs_index_set, command_arg_key_specs_index_set):
+ if not args:
+ return True
+
+ for arg in args:
+ if arg.key_spec_index is not None:
+ assert isinstance(arg.key_spec_index, int)
+
+ if arg.key_spec_index not in command_key_specs_index_set:
+ print("command: %s arg: %s key_spec_index error" % (command.fullname(), arg.name))
+ return False
+
+ command_arg_key_specs_index_set.add(arg.key_spec_index)
+
+ if not check_command_args_key_specs(arg.subargs, command_key_specs_index_set, command_arg_key_specs_index_set):
+ return False
+
+ return True
+
+def check_command_key_specs(command):
+ if not command.key_specs:
+ return True
+
+ assert isinstance(command.key_specs, list)
+
+ for cmd_key_spec in command.key_specs:
+ if "flags" not in cmd_key_spec:
+ print("command: %s key_specs missing flags" % command.fullname())
+ return False
+
+ if "NOT_KEY" in cmd_key_spec["flags"]:
+ # Like SUNSUBSCRIBE / SPUBLISH / SSUBSCRIBE
+ return True
+
+ command_key_specs_index_set = set(range(len(command.key_specs)))
+ command_arg_key_specs_index_set = set()
+
+ # Collect key_spec used for each arg, including arg.subarg
+ if not check_command_args_key_specs(command.args, command_key_specs_index_set, command_arg_key_specs_index_set):
+ return False
+
+ # Check if we have key_specs not used
+ if command_key_specs_index_set != command_arg_key_specs_index_set:
+ print("command: %s may have unused key_spec" % command.fullname())
+ return False
+
+ return True
+
+
# Globals
subcommands = {} # container_name -> dict(subcommand_name -> Subcommand) - Only subcommands
commands = {} # command_name -> Command - Only commands
@@ -132,6 +180,7 @@ class Argument(object):
self.desc = desc
self.name = self.desc["name"].lower()
self.type = self.desc["type"]
+ self.key_spec_index = self.desc.get("key_spec_index", None)
self.parent_name = parent_name
self.subargs = []
self.subargs_name = None
@@ -200,6 +249,7 @@ class Command(object):
self.name = name.upper()
self.desc = desc
self.group = self.desc["group"]
+ self.key_specs = self.desc.get("key_specs", [])
self.subcommands = []
self.args = []
for arg_desc in self.desc.get("arguments", []):
@@ -271,7 +321,7 @@ class Command(object):
def _key_specs_code():
s = ""
- for spec in self.desc.get("key_specs", []):
+ for spec in self.key_specs:
s += "{%s}," % KeySpec(spec).struct_code()
return s[:-1]
@@ -398,6 +448,17 @@ for command in commands.values():
subcommand.group = command.group
command.subcommands.append(subcommand)
+check_command_error_counter = 0 # An error counter is used to count errors in command checking.
+
+print("Checking all commands...")
+for command in commands.values():
+ if not check_command_key_specs(command):
+ check_command_error_counter += 1
+
+if check_command_error_counter != 0:
+ print("Error: There are errors in the commands check, please check the above logs.")
+ exit(1)
+
print("Generating commands.c...")
with open("%s/commands.c" % srcdir, "w") as f:
f.write("/* Automatically generated by %s, do not edit. */\n\n" % os.path.basename(__file__))
diff --git a/utils/generate-commands-json.py b/utils/generate-commands-json.py
index 8f812f224..23782ea22 100755
--- a/utils/generate-commands-json.py
+++ b/utils/generate-commands-json.py
@@ -1,10 +1,10 @@
#!/usr/bin/env python3
import argparse
import json
+import os
import subprocess
from collections import OrderedDict
-from sys import argv, stdin
-import os
+from sys import argv
def convert_flags_to_boolean_dict(flags):
@@ -118,7 +118,8 @@ if __name__ == '__main__':
stdout, stderr = p.communicate()
commands = json.loads(stdout)
- p = subprocess.Popen([args.cli, '-h', args.host, '-p', str(args.port), '--json', 'command', 'docs'], stdout=subprocess.PIPE)
+ p = subprocess.Popen([args.cli, '-h', args.host, '-p', str(args.port), '--json', 'command', 'docs'],
+ stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
docs = json.loads(stdout)