@@ -51,7 +51,7 @@ fn lfs_skip_smudge() -> bool {
5151/// This delegates to libgit2's attribute lookup and returns an [`LfsFilter`]
5252/// variant so downstream code can pattern-match instead of inspecting strings
5353/// or booleans.
54- pub fn lfs_filter_for ( repo : & Repository , path : & Path ) -> LfsFilter {
54+ pub fn filter_for ( repo : & Repository , path : & Path ) -> LfsFilter {
5555 match repo. get_attr ( path, "filter" , git2:: AttrCheckFlags :: empty ( ) )
5656 {
5757 Ok ( Some ( "lfs" ) ) => LfsFilter :: Lfs ,
@@ -63,7 +63,7 @@ pub fn lfs_filter_for(repo: &Repository, path: &Path) -> LfsFilter {
6363///
6464/// The real bytes are written to `.git/lfs/objects/`; keeping the index entry holding
6565/// just the small pointer text.
66- pub fn large_file_storage_clean_and_stage (
66+ pub fn clean_and_stage (
6767 repository : & Repository ,
6868 index : & mut git2:: Index ,
6969 file_path : & Path ,
@@ -147,7 +147,7 @@ fn file_mode_for(path: &Path) -> git2::FileMode {
147147/// Walk `tree` and smudge every LFS pointer file in the working tree.
148148///
149149/// Returns `Ok(())` even when individual files cannot be smudged, so a partial LFS store only warns.
150- pub fn large_file_storage_smudge_tree (
150+ pub fn smudge_tree (
151151 repository : & Repository ,
152152 target_tree : & git2:: Tree ,
153153 previous_tree : Option < & git2:: Tree > ,
@@ -198,7 +198,7 @@ pub fn large_file_storage_smudge_tree(
198198 for file_path in changed_file_paths {
199199 // Staging will clean content into the local LFS store
200200 // Checkout will smudge pointer files into their OG content
201- if lfs_filter_for ( repository, file_path) . is_lfs ( ) {
201+ if filter_for ( repository, file_path) . is_lfs ( ) {
202202 let full_path = working_directory. join ( file_path) ;
203203 let outcome =
204204 smudge_file ( & store, full_path. as_path ( ) , file_path) ;
@@ -210,6 +210,25 @@ pub fn large_file_storage_smudge_tree(
210210 Ok ( ( ) )
211211}
212212
213+ /// Smudge LFS pointer files in the working tree against `HEAD`, logging a
214+ /// warning tagged with `operation` on failure instead of propagating it.
215+ pub fn record_smudge ( repository : & Repository , operation : & str ) {
216+ // Operations that rewrite the working tree from git history (reset, stash
217+ // apply/pop, rebase, revert) leave LFS files as pointer text, so cover that here.
218+ let head_tree =
219+ match repository. head ( ) . and_then ( |h| h. peel_to_tree ( ) ) {
220+ Ok ( tree) => tree,
221+ Err ( e) => {
222+ log:: warn!( "{operation}: LFS smudge failed to resolve HEAD: {e}" ) ;
223+ return ;
224+ }
225+ } ;
226+
227+ if let Err ( e) = smudge_tree ( repository, & head_tree, None ) {
228+ log:: warn!( "{operation}: LFS smudge failed: {e}" ) ;
229+ }
230+ }
231+
213232fn log_smudge_outcome (
214233 entry_path : & Path ,
215234 outcome : Result < SmudgeOutcome > ,
@@ -259,11 +278,8 @@ fn smudge_tree_entries(
259278 }
260279 // Use a match guard to gracefully filter out non-LFS blobs immediately
261280 Some ( git2:: ObjectType :: Blob )
262- if lfs_filter_for (
263- repository,
264- entry_path. as_path ( ) ,
265- )
266- . is_lfs ( ) =>
281+ if filter_for ( repository, entry_path. as_path ( ) )
282+ . is_lfs ( ) =>
267283 {
268284 let full_path = working_directory. join ( & entry_path) ;
269285 let outcome = smudge_file (
0 commit comments