@@ -3,6 +3,8 @@ from __future__ import annotations
33import argparse
44import collections
55import dataclasses
6+ import glob
7+ import hashlib
68import os .path
79import re
810import shlex
@@ -131,7 +133,7 @@ def main():
131133 )
132134 slot_ids : list [str ] = " " .join (args .slot_id ).split ()
133135 local_dir : str = re .sub (r"/+$" , "" , args .local_dir )
134- hints : list [str ] = " " . join ( args .hint ). split ()
136+ hints : list [str ] = [ hint for arg in args .hint for hint in expand_hint_arg ( arg = arg )]
135137 exclude : list [str ] = [
136138 line for line in "\n " .join (args .exclude ).splitlines () if line .strip ()
137139 ]
@@ -631,6 +633,50 @@ def check_call(
631633 print (elapsed )
632634
633635
636+ #
637+ # Given a hint argument value, expands it to hints:
638+ # - If the argument starts with "@", then it expands to a digest of the content
639+ # of all files matching the space-separated list of patterns after the "@".
640+ # - If the argument contains multiple space-separated values, then it treats
641+ # them as a list of hints.
642+ #
643+ def expand_hint_arg (* , arg : str ) -> list [str ]:
644+ if arg .startswith ("@" ):
645+ items = arg [1 :].strip ().split ()
646+ item_patterns = [item for item in items if is_wildcard (item )]
647+ item_files = [item for item in items if not is_wildcard (item )]
648+ files = sorted (
649+ [
650+ * item_files ,
651+ * [
652+ file
653+ for pattern in item_patterns
654+ for file in glob .glob (pattern , recursive = True )
655+ ],
656+ ]
657+ )
658+ print (cmd_to_debug_prompt (["sha256sum" , * files ]))
659+ m = hashlib .sha256 ()
660+ for file in files :
661+ try :
662+ with open (file , "rb" ) as f :
663+ m .update (f .read ())
664+ except OSError as e :
665+ raise UserException (f"{ e .strerror } : { e .filename } " )
666+ hint = "@" + m .hexdigest ()[0 :16 ]
667+ print (f" { hint } " )
668+ return [hint ]
669+ else :
670+ return arg .strip ().split ()
671+
672+
673+ #
674+ # Returns true if the path is a wildcard pattern.
675+ #
676+ def is_wildcard (path : str ) -> bool :
677+ return "*" in path or "?" in path
678+
679+
634680#
635681# Converts a command to a debug string like:
636682# - "$ some command"
0 commit comments