@@ -19,7 +19,6 @@ use configmodel::Config;
1919use configmodel:: ConfigExt ;
2020use identity:: dotgit:: follow_dotgit_path;
2121use spawn_ext:: CommandExt ;
22- use types:: HgId ;
2322
2423/// Run `git` outside a repo.
2524#[ derive( Default , Clone ) ]
@@ -185,98 +184,6 @@ impl RepoGit {
185184 pub fn root ( & self ) -> & Path {
186185 & self . root
187186 }
188-
189- /// Convert `git diff-index --norenames --raw -z <tree-ish>` output
190- /// into `git update-index -z --index-info` input.
191- ///
192- /// diff-index entry format:
193- /// `:<old_mode> <new_mode> <old_sha> <new_sha> <status>\0<path>\0`
194- ///
195- /// See https://git-scm.com/docs/git-diff-index#_raw_output_format
196- ///
197- /// `git update-index --index-info` format:
198- /// `<old_mode> <old_sha> <stage>\t<path>\0`
199- ///
200- /// See https://git-scm.com/docs/git-update-index#_using_index_info
201- fn diff_index_to_index_info ( raw : & [ u8 ] ) -> io:: Result < Vec < u8 > > {
202- let mut result = Vec :: new ( ) ;
203- let mut pos = 0 ;
204-
205- let parse_err = |msg : & str | io:: Error :: new ( io:: ErrorKind :: InvalidData , msg. to_owned ( ) ) ;
206-
207- while pos < raw. len ( ) {
208- // Each entry starts with ':'
209- if raw[ pos] != b':' {
210- return Err ( parse_err ( "missing ':' at the beginning" ) ) ;
211- }
212- pos += 1 ;
213-
214- // Header ends at the first \0: "<old_mode> <new_mode> <old_sha> <new_sha> <status>"
215- let header_end = raw[ pos..]
216- . iter ( )
217- . position ( |& b| b == 0 )
218- . ok_or_else ( || parse_err ( "no NUL in the entry" ) ) ?
219- + pos;
220-
221- let header = std:: str:: from_utf8 ( & raw [ pos..header_end] )
222- . map_err ( |e| parse_err ( & e. to_string ( ) ) ) ?;
223-
224- // Split: old_mode, new_mode, old_sha, new_sha, status
225- let mut parts = header. splitn ( 5 , ' ' ) ;
226- let old_mode = parts. next ( ) . ok_or_else ( || parse_err ( "missing old_mode" ) ) ?;
227- parts. next ( ) ; // new_mode
228- let old_sha = parts. next ( ) . ok_or_else ( || parse_err ( "missing old_sha" ) ) ?;
229- parts. next ( ) ; // new_sha
230- let status = parts. next ( ) . ok_or_else ( || parse_err ( "missing status" ) ) ?;
231-
232- // Copy (C) and rename (R) should be opted out by the diff-index command.
233- // Copied and renamed files show up as addition (A) and deletion (D) instead.
234- // Unmerged (U) status should not show up as Sapling does not expose merge conflicts to Git.
235- match status {
236- "M" | "A" | "D" | "T" => { }
237- _ => {
238- return Err ( parse_err ( & format ! (
239- "unexpected diff-index status: {status}"
240- ) ) ) ;
241- }
242- }
243-
244- // Remaining: \0<path>\0
245- pos = header_end + 1 ;
246- let path_end = raw[ pos..]
247- . iter ( )
248- . position ( |& b| b == 0 )
249- . ok_or_else ( || parse_err ( "missing NUL after path" ) ) ?
250- + pos;
251- let path = & raw [ pos..path_end] ;
252- pos = path_end + 1 ;
253-
254- // <mode>SP<sha1>SP<stage>TAB<path>
255- result. extend_from_slice ( old_mode. as_bytes ( ) ) ;
256- result. push ( b' ' ) ;
257- result. extend_from_slice ( old_sha. as_bytes ( ) ) ;
258- result. extend_from_slice ( b" 0\t " ) ;
259- result. extend_from_slice ( path) ;
260- result. push ( b'\0' ) ;
261- }
262-
263- Ok ( result)
264- }
265-
266- /// Update git index for mutated paths compared to given commit.
267- /// Uses `--index-info` to avoid command-line argument length limits.
268- pub fn update_diff_index ( & self , treeish : HgId ) -> io:: Result < ExitStatus > {
269- let hex = treeish. to_hex ( ) ;
270- let output = self . call (
271- "diff-index" ,
272- & [ "--cached" , "--no-renames" , "--raw" , "-z" , & hex] ,
273- ) ?;
274-
275- let index_info = Self :: diff_index_to_index_info ( & output. stdout ) ?;
276-
277- let mut cmd = self . git_cmd ( "update-index" , & [ "-z" , "--index-info" ] ) ;
278- cmd. checked_run_with_stdin ( & index_info)
279- }
280187}
281188
282189impl Deref for BareGit {
@@ -417,33 +324,3 @@ fn git_cmd_impl(
417324
418325 cmd
419326}
420-
421- #[ cfg( test) ]
422- mod tests {
423- use super :: * ;
424-
425- #[ test]
426- fn test_diff_index_to_index_info ( ) {
427- // Empty input
428- assert_eq ! ( RepoGit :: diff_index_to_index_info( b"" ) . unwrap( ) , b"" ) ;
429-
430- let raw = b":100644 100644 aaaa bbbb M\0 modifiedfile\0 \
431- :000000 100644 0000 bbbb A\0 addedfile\0 \
432- :100755 000000 aaaa 0000 D\0 deletedfile\0 ";
433- let out = RepoGit :: diff_index_to_index_info ( raw) . unwrap ( ) ;
434- assert_eq ! (
435- out,
436- b"100644 aaaa 0\t modifiedfile\0 \
437- 000000 0000 0\t addedfile\0 \
438- 100755 aaaa 0\t deletedfile\0 "
439- ) ;
440- }
441-
442- #[ test]
443- fn test_diff_index_with_unexpected_status ( ) {
444- let raw = b":000000 000000 0000 0000 U\0 unmergedfile\0 " ;
445- let err = RepoGit :: diff_index_to_index_info ( raw) . unwrap_err ( ) ;
446- assert_eq ! ( err. kind( ) , io:: ErrorKind :: InvalidData ) ;
447- assert ! ( err. to_string( ) . contains( "unexpected diff-index status: U" ) ) ;
448- }
449- }
0 commit comments