@@ -19,7 +19,7 @@ pub mod pipeline {
19
19
pub mod options {
20
20
use crate :: { bstr:: BString , config} ;
21
21
22
- /// The error returned by [Pipeline::options()][ crate::filter::Pipeline::options()] .
22
+ /// The error returned by [Pipeline::options()]( crate::filter::Pipeline::options()) .
23
23
#[ derive( Debug , thiserror:: Error ) ]
24
24
#[ allow( missing_docs) ]
25
25
pub enum Error {
@@ -39,7 +39,7 @@ pub mod pipeline {
39
39
40
40
///
41
41
pub mod convert_to_git {
42
- /// The error returned by [Pipeline::convert_to_git()][ crate::filter::Pipeline::convert_to_git()] .
42
+ /// The error returned by [Pipeline::convert_to_git()]( crate::filter::Pipeline::convert_to_git()) .
43
43
#[ derive( Debug , thiserror:: Error ) ]
44
44
#[ allow( missing_docs) ]
45
45
pub enum Error {
@@ -52,7 +52,7 @@ pub mod pipeline {
52
52
53
53
///
54
54
pub mod convert_to_worktree {
55
- /// The error returned by [Pipeline::convert_to_worktree()][ crate::filter::Pipeline::convert_to_worktree()] .
55
+ /// The error returned by [Pipeline::convert_to_worktree()]( crate::filter::Pipeline::convert_to_worktree()) .
56
56
#[ derive( Debug , thiserror:: Error ) ]
57
57
#[ allow( missing_docs) ]
58
58
pub enum Error {
@@ -62,6 +62,25 @@ pub mod pipeline {
62
62
Convert ( #[ from] gix_filter:: pipeline:: convert:: to_worktree:: Error ) ,
63
63
}
64
64
}
65
+
66
+ ///
67
+ pub mod worktree_file_to_object {
68
+ use std:: path:: PathBuf ;
69
+
70
+ /// The error returned by [Pipeline::worktree_file_to_object()](crate::filter::Pipeline::worktree_file_to_object()).
71
+ #[ derive( Debug , thiserror:: Error ) ]
72
+ #[ allow( missing_docs) ]
73
+ pub enum Error {
74
+ #[ error( "Cannot add worktree files in bare repositories" ) ]
75
+ MissingWorktree ,
76
+ #[ error( "Failed to perform IO for object creation for '{}'" , path. display( ) ) ]
77
+ IO { source : std:: io:: Error , path : PathBuf } ,
78
+ #[ error( transparent) ]
79
+ WriteBlob ( #[ from] crate :: object:: write:: Error ) ,
80
+ #[ error( transparent) ]
81
+ ConvertToGit ( #[ from] crate :: filter:: pipeline:: convert_to_git:: Error ) ,
82
+ }
83
+ }
65
84
}
66
85
67
86
/// A git pipeline for transforming data *to-git* and *to-worktree*, based
@@ -133,7 +152,7 @@ impl Pipeline<'_> {
133
152
/// Convert a `src` stream (to be found at `rela_path`, a repo-relative path) to a representation suitable for storage in `git`
134
153
/// by using all attributes at `rela_path` and configuration of the repository to know exactly which filters apply.
135
154
/// `index` is used in particularly rare cases where the CRLF filter in auto-mode tries to determine whether to apply itself,
136
- /// and it should match the state used when [instantiating this instance][ Self::new()] .
155
+ /// and it should match the state used when [instantiating this instance]( Self::new()) .
137
156
/// Note that the return-type implements [`std::io::Read`].
138
157
pub fn convert_to_git < R > (
139
158
& mut self ,
@@ -187,6 +206,63 @@ impl Pipeline<'_> {
187
206
) ?)
188
207
}
189
208
209
+ /// Add the worktree file at `rela_path` to the object database and return its `(id, entry)` for use in a tree or in the index, for instance.
210
+ ///
211
+ /// `index` is used in particularly rare cases where the CRLF filter in auto-mode tries to determine whether to apply itself,
212
+ /// and it should match the state used when [instantiating this instance](Self::new()).
213
+ ///
214
+ /// Return `Ok(None)` the file didn't exist in the worktree, or if it was of an untrackable type.
215
+ pub fn worktree_file_to_object (
216
+ & mut self ,
217
+ rela_path : & BStr ,
218
+ index : & gix_index:: State ,
219
+ ) -> Result < Option < ( gix_hash:: ObjectId , gix_object:: tree:: EntryKind ) > , pipeline:: worktree_file_to_object:: Error >
220
+ {
221
+ use pipeline:: worktree_file_to_object:: Error ;
222
+
223
+ let rela_path_as_path = gix_path:: from_bstr ( rela_path) ;
224
+ let repo = self . repo ;
225
+ let worktree_dir = repo. work_dir ( ) . ok_or ( Error :: MissingWorktree ) ?;
226
+ let path = worktree_dir. join ( & rela_path_as_path) ;
227
+ let md = match std:: fs:: symlink_metadata ( & path) {
228
+ Ok ( md) => md,
229
+ Err ( err) => {
230
+ if gix_fs:: io_err:: is_not_found ( err. kind ( ) , err. raw_os_error ( ) ) {
231
+ return Ok ( None ) ;
232
+ } else {
233
+ return Err ( Error :: IO { source : err, path } ) ;
234
+ }
235
+ }
236
+ } ;
237
+ let ( id, kind) = if md. is_symlink ( ) {
238
+ let target = std:: fs:: read_link ( & path) . map_err ( |source| Error :: IO { source, path } ) ?;
239
+ let id = repo. write_blob ( gix_path:: into_bstr ( target) . as_ref ( ) ) ?;
240
+ ( id, gix_object:: tree:: EntryKind :: Link )
241
+ } else if md. is_file ( ) {
242
+ use gix_filter:: pipeline:: convert:: ToGitOutcome ;
243
+
244
+ let file = std:: fs:: File :: open ( & path) . map_err ( |source| Error :: IO { source, path } ) ?;
245
+ let file_for_git = self . convert_to_git ( file, rela_path_as_path. as_ref ( ) , index) ?;
246
+ let id = match file_for_git {
247
+ ToGitOutcome :: Unchanged ( mut file) => repo. write_blob_stream ( & mut file) ?,
248
+ ToGitOutcome :: Buffer ( buf) => repo. write_blob ( buf) ?,
249
+ ToGitOutcome :: Process ( mut read) => repo. write_blob_stream ( & mut read) ?,
250
+ } ;
251
+
252
+ let kind = if gix_fs:: is_executable ( & md) {
253
+ gix_object:: tree:: EntryKind :: BlobExecutable
254
+ } else {
255
+ gix_object:: tree:: EntryKind :: Blob
256
+ } ;
257
+ ( id, kind)
258
+ } else {
259
+ // This is probably a type-change to something we can't track.
260
+ return Ok ( None ) ;
261
+ } ;
262
+
263
+ Ok ( Some ( ( id. detach ( ) , kind) ) )
264
+ }
265
+
190
266
/// Retrieve the static context that is made available to the process filters.
191
267
///
192
268
/// The context set here is relevant for the [`convert_to_git()`][Self::convert_to_git()] and
0 commit comments