11use std:: collections:: hash_map:: Entry ;
22use std:: fmt:: Write ;
3+ use std:: io;
34use std:: path:: { Path , PathBuf } ;
45
56use anyhow:: { bail, Context , Result } ;
@@ -44,7 +45,7 @@ use crate::commands::pip::loggers::{
4445use crate :: commands:: pip:: operations:: Modifications ;
4546use crate :: commands:: project:: lock:: LockMode ;
4647use crate :: commands:: project:: {
47- init_script_python_requirement, validate_script_requires_python, ProjectError ,
48+ init_script_python_requirement, lock , validate_script_requires_python, ProjectError ,
4849 ProjectInterpreter , ScriptPython ,
4950} ;
5051use crate :: commands:: reporters:: { PythonDownloadReporter , ResolverReporter } ;
@@ -618,8 +619,10 @@ pub(crate) async fn add(
618619 }
619620
620621 // Store the content prior to any modifications.
621- let existing = project. pyproject_toml ( ) . as_ref ( ) . to_vec ( ) ;
622- let root = project. root ( ) . to_path_buf ( ) ;
622+ let project_root = project. root ( ) . to_path_buf ( ) ;
623+ let workspace_root = project. workspace ( ) . install_path ( ) . to_path_buf ( ) ;
624+ let existing_pyproject_toml = project. pyproject_toml ( ) . as_ref ( ) . to_vec ( ) ;
625+ let existing_uv_lock = lock:: read_bytes ( project. workspace ( ) ) . await ?;
623626
624627 // Update the `pypackage.toml` in-memory.
625628 let project = project
@@ -628,12 +631,18 @@ pub(crate) async fn add(
628631
629632 // Set the Ctrl-C handler to revert changes on exit.
630633 let _ = ctrlc:: set_handler ( {
631- let root = root. clone ( ) ;
632- let existing = existing. clone ( ) ;
634+ let project_root = project_root. clone ( ) ;
635+ let workspace_root = workspace_root. clone ( ) ;
636+ let existing_pyproject_toml = existing_pyproject_toml. clone ( ) ;
637+ let existing_uv_lock = existing_uv_lock. clone ( ) ;
633638 move || {
634- // Revert the changes to the `pyproject.toml`, if necessary.
635639 if modified {
636- let _ = fs_err:: write ( root. join ( "pyproject.toml" ) , & existing) ;
640+ let _ = revert (
641+ & project_root,
642+ & workspace_root,
643+ & existing_pyproject_toml,
644+ existing_uv_lock. as_deref ( ) ,
645+ ) ;
637646 }
638647
639648 #[ allow( clippy:: exit, clippy:: cast_possible_wrap) ]
@@ -667,9 +676,13 @@ pub(crate) async fn add(
667676 {
668677 Ok ( ( ) ) => Ok ( ExitStatus :: Success ) ,
669678 Err ( err) => {
670- // Revert the changes to the `pyproject.toml`, if necessary.
671679 if modified {
672- fs_err:: write ( root. join ( "pyproject.toml" ) , & existing) ?;
680+ revert (
681+ & project_root,
682+ & workspace_root,
683+ & existing_pyproject_toml,
684+ existing_uv_lock. as_deref ( ) ,
685+ ) ?;
673686 }
674687
675688 match err {
@@ -691,13 +704,7 @@ pub(crate) async fn add(
691704 diagnostics:: build ( dist, err) ;
692705 Ok ( ExitStatus :: Failure )
693706 }
694- err => {
695- // Revert the changes to the `pyproject.toml`, if necessary.
696- if modified {
697- fs_err:: write ( root. join ( "pyproject.toml" ) , & existing) ?;
698- }
699- Err ( err. into ( ) )
700- }
707+ err => Err ( err. into ( ) ) ,
701708 }
702709 }
703710 }
@@ -931,6 +938,25 @@ async fn lock_and_sync(
931938 Ok ( ( ) )
932939}
933940
941+ /// Revert the changes to the `pyproject.toml` and `uv.lock`, if necessary.
942+ fn revert (
943+ project_root : & Path ,
944+ workspace_root : & Path ,
945+ pyproject_toml : & [ u8 ] ,
946+ uv_lock : Option < & [ u8 ] > ,
947+ ) -> Result < ( ) , io:: Error > {
948+ debug ! ( "Reverting changes to `pyproject.toml`" ) ;
949+ fs_err:: write ( project_root. join ( "pyproject.toml" ) , pyproject_toml) ?;
950+ if let Some ( uv_lock) = uv_lock. as_ref ( ) {
951+ debug ! ( "Reverting changes to `uv.lock`" ) ;
952+ fs_err:: write ( workspace_root. join ( "uv.lock" ) , uv_lock) ?;
953+ } else {
954+ debug ! ( "Removing `uv.lock`" ) ;
955+ fs_err:: remove_file ( workspace_root. join ( "uv.lock" ) ) ?;
956+ }
957+ Ok ( ( ) )
958+ }
959+
934960/// Augment a user-provided requirement by attaching any specification data that was provided
935961/// separately from the requirement itself (e.g., `--branch main`).
936962fn augment_requirement (
0 commit comments