@@ -6,6 +6,7 @@ use gix::diff::blob::UnifiedDiff;
66use gix:: objs:: tree:: EntryMode ;
77use gix:: odb:: store:: RefreshMode ;
88use gix:: prelude:: ObjectIdExt ;
9+ use gix:: ObjectId ;
910
1011pub fn tree (
1112 mut repo : gix:: Repository ,
@@ -116,6 +117,38 @@ fn typed_location(mut location: BString, mode: EntryMode) -> BString {
116117 location
117118}
118119
120+ fn resolve_revspec (
121+ repo : & gix:: Repository ,
122+ revspec : BString ,
123+ ) -> Result < ( ObjectId , Option < std:: path:: PathBuf > , BString ) , anyhow:: Error > {
124+ let result = repo. rev_parse ( revspec. as_bstr ( ) ) ;
125+
126+ match result {
127+ Err ( gix:: revision:: spec:: parse:: Error :: FindReference ( gix:: refs:: file:: find:: existing:: Error :: NotFound {
128+ name,
129+ } ) ) => {
130+ use std:: os:: unix:: ffi:: OsStrExt ;
131+
132+ let root: Option < std:: path:: PathBuf > = repo. workdir ( ) . map ( std:: path:: Path :: to_path_buf) ;
133+ let name: BString = BString :: new ( name. as_os_str ( ) . as_bytes ( ) . to_vec ( ) ) ;
134+
135+ Ok ( ( ObjectId :: null ( gix:: hash:: Kind :: Sha1 ) , root, name) )
136+ }
137+ Err ( err) => Err ( err. into ( ) ) ,
138+ Ok ( resolved_revspec) => {
139+ let blob_id = resolved_revspec
140+ . single ( )
141+ . context ( format ! ( "rev-spec '{revspec}' must resolve to a single object" ) ) ?;
142+
143+ let ( path, _) = resolved_revspec
144+ . path_and_mode ( )
145+ . context ( format ! ( "rev-spec '{revspec}' must contain a path" ) ) ?;
146+
147+ Ok ( ( blob_id. into ( ) , None , path. into ( ) ) )
148+ }
149+ }
150+ }
151+
119152pub fn file (
120153 mut repo : gix:: Repository ,
121154 out : & mut dyn std:: io:: Write ,
@@ -125,39 +158,27 @@ pub fn file(
125158 repo. object_cache_size_if_unset ( repo. compute_object_cache_size_for_tree_diffs ( & * * repo. index_or_empty ( ) ?) ) ;
126159 repo. objects . refresh = RefreshMode :: Never ;
127160
128- let old_resolved_revspec = repo. rev_parse ( old_revspec. as_bstr ( ) ) ?;
129- let new_resolved_revspec = repo. rev_parse ( new_revspec. as_bstr ( ) ) ?;
130-
131- let old_blob_id = old_resolved_revspec
132- . single ( )
133- . context ( format ! ( "rev-spec '{old_revspec}' must resolve to a single object" ) ) ?;
134- let new_blob_id = new_resolved_revspec
135- . single ( )
136- . context ( format ! ( "rev-spec '{new_revspec}' must resolve to a single object" ) ) ?;
161+ let ( old_blob_id, old_root, old_path) = resolve_revspec ( & repo, old_revspec) ?;
162+ let ( new_blob_id, new_root, new_path) = resolve_revspec ( & repo, new_revspec) ?;
137163
138- let ( old_path, _) = old_resolved_revspec
139- . path_and_mode ( )
140- . context ( format ! ( "rev-spec '{old_revspec}' must contain a path" ) ) ?;
141- let ( new_path, _) = new_resolved_revspec
142- . path_and_mode ( )
143- . context ( format ! ( "rev-spec '{new_revspec}' must contain a path" ) ) ?;
164+ let worktree_roots = gix:: diff:: blob:: pipeline:: WorktreeRoots { old_root, new_root } ;
144165
145166 let mut resource_cache = repo. diff_resource_cache (
146167 gix:: diff:: blob:: pipeline:: Mode :: ToGitUnlessBinaryToTextIsPresent ,
147- Default :: default ( ) ,
168+ worktree_roots ,
148169 ) ?;
149170
150171 resource_cache. set_resource (
151- old_blob_id. into ( ) ,
172+ old_blob_id,
152173 gix:: object:: tree:: EntryKind :: Blob ,
153- old_path,
174+ old_path. as_ref ( ) ,
154175 gix:: diff:: blob:: ResourceKind :: OldOrSource ,
155176 & repo. objects ,
156177 ) ?;
157178 resource_cache. set_resource (
158- new_blob_id. into ( ) ,
179+ new_blob_id,
159180 gix:: object:: tree:: EntryKind :: Blob ,
160- new_path,
181+ new_path. as_ref ( ) ,
161182 gix:: diff:: blob:: ResourceKind :: NewOrDestination ,
162183 & repo. objects ,
163184 ) ?;
0 commit comments