@@ -118,8 +118,9 @@ def _lock_impl(ctx):
118118 args .run_shell .add ("--quiet" )
119119
120120 # Generate a wrapper script that copies the existing output (if any) and
121- # then forwards all remaining arguments to uv. This approach works on both
122- # POSIX (bash, via $@) and Windows (cmd.exe, via %* in a .bat file).
121+ # then runs uv. On POSIX, args are forwarded via exec "$@". On Windows,
122+ # the full command line is embedded in the .bat file with backslash paths
123+ # (CMD doesn't recognize forward slashes in executable paths).
123124 if ctx .attr .is_windows :
124125 ext = ".bat"
125126 lines = ["@echo off" ]
@@ -149,7 +150,22 @@ def _lock_impl(ctx):
149150 ))
150151
151152 if ctx .attr .is_windows :
152- lines .append ("%*" )
153+ # Build the command line with backslash paths for CMD.
154+ # args.run_info has most args; add the output/progress/quiet
155+ # args that were only added directly to args.run_shell.
156+ def _quote (arg ):
157+ if hasattr (arg , "short_path" ):
158+ arg = arg .short_path
159+ arg = arg .replace ("/" , "\\ " )
160+ return '"' + arg .replace ('"' , '""' ) + '"'
161+
162+ bat_args = args .run_info + [
163+ "--output-file" ,
164+ output ,
165+ "--no-progress" ,
166+ "--quiet" ,
167+ ]
168+ lines .append (" " .join ([_quote (a ) for a in bat_args ]))
153169 else :
154170 lines .append ('exec "$@"' )
155171
@@ -167,7 +183,10 @@ def _lock_impl(ctx):
167183 inputs = srcs + ctx .files .existing_output ,
168184 mnemonic = "PyRequirementsLockUv" ,
169185 outputs = [output ],
170- arguments = [args .run_shell ],
186+ # On Windows, the command line is embedded directly in the .bat
187+ # script (with backslash paths). On POSIX, args are forwarded via
188+ # exec "$@" in the .sh script.
189+ arguments = [args .run_shell ] if not ctx .attr .is_windows else [],
171190 tools = [
172191 uv ,
173192 python_files ,
0 commit comments