77use axum:: extract:: Path ;
88use axum:: Json ;
99use crates_io_worker:: BackgroundJob ;
10- use diesel:: { ExpressionMethods , RunQueryDsl } ;
10+ use diesel:: { ExpressionMethods , QueryDsl , RunQueryDsl } ;
1111use diesel_async:: async_connection_wrapper:: AsyncConnectionWrapper ;
1212use http:: request:: Parts ;
1313use http:: StatusCode ;
@@ -142,7 +142,47 @@ fn apply_yank_update(
142142) -> AppResult < ( ) > {
143143 // Try to update the yank state first, to avoid unnecessary checks.
144144 update_version_yank_state ( version, update_data) ?;
145+ perform_version_yank_update ( state, req, conn, version, krate) ?;
145146
147+ Ok ( ( ) )
148+ }
149+
150+ fn update_version_yank_state ( version : & mut Version , update_data : & VersionUpdate ) -> AppResult < ( ) > {
151+ match ( update_data. yanked , & update_data. yank_message ) {
152+ ( Some ( true ) , Some ( message) ) => {
153+ version. yanked = true ;
154+ version. yank_message = Some ( message. clone ( ) ) ;
155+ }
156+ ( Some ( yanked) , None ) => {
157+ version. yanked = yanked;
158+ version. yank_message = None ;
159+ }
160+ ( Some ( false ) , Some ( _) ) => {
161+ return Err ( bad_request ( "Cannot set yank message when unyanking" ) ) ;
162+ }
163+ ( None , Some ( message) ) => {
164+ if version. yanked {
165+ version. yank_message = Some ( message. clone ( ) ) ;
166+ } else {
167+ return Err ( bad_request (
168+ "Cannot update yank message for a version that is not yanked" ,
169+ ) ) ;
170+ }
171+ }
172+ // If both yanked and yank_message are None, do nothing.
173+ // This function only cares about updating the yanked state and yank message.
174+ ( None , None ) => { }
175+ }
176+ Ok ( ( ) )
177+ }
178+
179+ pub fn perform_version_yank_update (
180+ state : & AppState ,
181+ req : & Parts ,
182+ conn : & mut impl Conn ,
183+ version : & Version ,
184+ krate : & Crate ,
185+ ) -> AppResult < ( ) > {
146186 // Add authentication check
147187 let auth = AuthCheck :: default ( )
148188 . with_endpoint_scope ( EndpointScope :: Yank )
@@ -168,12 +208,27 @@ fn apply_yank_update(
168208 } else {
169209 return Err ( custom (
170210 StatusCode :: FORBIDDEN ,
171- "must already be an owner to update version " ,
211+ "must already be an owner to yank or unyank " ,
172212 ) ) ;
173213 }
174214 }
175215
176- diesel:: update ( & * version)
216+ // Check if the yanked state or yank message has changed
217+ let ( yanked, yank_message) = crate :: schema:: versions:: table
218+ . find ( version. id )
219+ . select ( (
220+ crate :: schema:: versions:: yanked,
221+ crate :: schema:: versions:: yank_message,
222+ ) )
223+ . first :: < ( bool , Option < String > ) > ( conn) ?;
224+
225+ if yanked == version. yanked && yank_message == version. yank_message {
226+ // No changes, return early
227+ return Ok ( ( ) ) ;
228+ }
229+
230+ // Proceed with the update
231+ diesel:: update ( version)
177232 . set ( (
178233 crate :: schema:: versions:: yanked. eq ( version. yanked ) ,
179234 crate :: schema:: versions:: yank_message. eq ( & version. yank_message ) ,
@@ -194,32 +249,3 @@ fn apply_yank_update(
194249
195250 Ok ( ( ) )
196251}
197-
198- fn update_version_yank_state ( version : & mut Version , update_data : & VersionUpdate ) -> AppResult < ( ) > {
199- match ( update_data. yanked , & update_data. yank_message ) {
200- ( Some ( true ) , Some ( message) ) => {
201- version. yanked = true ;
202- version. yank_message = Some ( message. clone ( ) ) ;
203- }
204- ( Some ( yanked) , None ) => {
205- version. yanked = yanked;
206- version. yank_message = None ;
207- }
208- ( Some ( false ) , Some ( _) ) => {
209- return Err ( bad_request ( "Cannot set yank message when unyanking" ) ) ;
210- }
211- ( None , Some ( message) ) => {
212- if version. yanked {
213- version. yank_message = Some ( message. clone ( ) ) ;
214- } else {
215- return Err ( bad_request (
216- "Cannot update yank message for a version that is not yanked" ,
217- ) ) ;
218- }
219- }
220- // If both yanked and yank_message are None, do nothing.
221- // This function only cares about updating the yanked state and yank message.
222- ( None , None ) => { }
223- }
224- Ok ( ( ) )
225- }
0 commit comments