@@ -35,6 +35,32 @@ def _json_line(payload: object) -> str:
3535_MAX_FEATURE_NUMBER = 2 ** 63 - 1
3636
3737
38+ def _int64_from_digits (value : str ) -> int | None :
39+ normalized = value .lstrip ("0" ) or "0"
40+ maximum = str (_MAX_FEATURE_NUMBER )
41+ if len (normalized ) > len (maximum ) or (
42+ len (normalized ) == len (maximum ) and normalized > maximum
43+ ):
44+ return None
45+ return int (normalized , 10 )
46+
47+
48+ def _persistence_assignments (
49+ branch_name : str , feature_dir : str , * , powershell : bool
50+ ) -> tuple [str , str ]:
51+ if powershell :
52+ quoted_branch = "'" + branch_name .replace ("'" , "''" ) + "'"
53+ quoted_dir = "'" + feature_dir .replace ("'" , "''" ) + "'"
54+ return (
55+ f"$env:SPECIFY_FEATURE = { quoted_branch } " ,
56+ f"$env:SPECIFY_FEATURE_DIRECTORY = { quoted_dir } " ,
57+ )
58+ return (
59+ f"export SPECIFY_FEATURE={ shlex .quote (branch_name )} " ,
60+ f"export SPECIFY_FEATURE_DIRECTORY={ shlex .quote (feature_dir )} " ,
61+ )
62+
63+
3864def _usage (argv0 : str ) -> str :
3965 return (
4066 f"Usage: { argv0 } [--json] [--dry-run] [--allow-existing-branch] "
@@ -172,8 +198,8 @@ def _get_highest_from_specs(specs_dir: Path) -> int:
172198 if re .match (r"^[0-9]{3,}-" , name ) and not re .match (
173199 r"^[0-9]{8}-[0-9]{6}-" , name
174200 ):
175- number = int (re .match (r"^[0-9]+" , name ).group (), 10 )
176- if number <= _MAX_FEATURE_NUMBER :
201+ number = _int64_from_digits (re .match (r"^[0-9]+" , name ).group ())
202+ if number is not None :
177203 highest = max (highest , number )
178204 return highest
179205
@@ -214,19 +240,14 @@ def main(argv: list[str] | None = None) -> int:
214240 file = sys .stderr ,
215241 )
216242 return 1
217- normalized_number = branch_number .lstrip ("0" ) or "0"
218- max_feature_number = str (_MAX_FEATURE_NUMBER )
219- if len (normalized_number ) > len (max_feature_number ) or (
220- len (normalized_number ) == len (max_feature_number )
221- and normalized_number > max_feature_number
222- ):
243+ number = _int64_from_digits (branch_number )
244+ if number is None :
223245 print (
224246 "Error: --number must be between 0 and "
225247 f"{ _MAX_FEATURE_NUMBER } , got '{ branch_number } '" ,
226248 file = sys .stderr ,
227249 )
228250 return 1
229- number = int (normalized_number , 10 )
230251 else :
231252 number = _get_highest_from_specs (specs_dir ) + 1
232253 if number > _MAX_FEATURE_NUMBER :
@@ -303,15 +324,13 @@ def main(argv: list[str] | None = None) -> int:
303324 persist_feature_json (repo_root , str (feature_dir ))
304325
305326 # Inform the user how to set feature state in their own shell.
306- print (
307- f"# To persist: export SPECIFY_FEATURE={ shlex .quote (branch_name )} " ,
308- file = sys .stderr ,
309- )
310- print (
311- "# export "
312- f"SPECIFY_FEATURE_DIRECTORY={ shlex .quote (str (feature_dir ))} " ,
313- file = sys .stderr ,
327+ feature_assignment , directory_assignment = _persistence_assignments (
328+ branch_name ,
329+ str (feature_dir ),
330+ powershell = sys .platform == "win32" ,
314331 )
332+ print (f"# To persist: { feature_assignment } " , file = sys .stderr )
333+ print (f"# { directory_assignment } " , file = sys .stderr )
315334
316335 if args .json_mode :
317336 payload : dict [str , object ] = {
@@ -327,14 +346,8 @@ def main(argv: list[str] | None = None) -> int:
327346 print (f"SPEC_FILE: { spec_file } " )
328347 print (f"FEATURE_NUM: { feature_num } " )
329348 if not args .dry_run :
330- print (
331- "# To persist in your shell: export "
332- f"SPECIFY_FEATURE={ shlex .quote (branch_name )} "
333- )
334- print (
335- "# export "
336- f"SPECIFY_FEATURE_DIRECTORY={ shlex .quote (str (feature_dir ))} "
337- )
349+ print (f"# To persist in your shell: { feature_assignment } " )
350+ print (f"# { directory_assignment } " )
338351 return 0
339352
340353
0 commit comments