@@ -11,7 +11,6 @@ import path from "path"
1111import z from "zod"
1212import { Global } from "../global"
1313import { Instance } from "../project/instance"
14- import { Filesystem } from "../util/filesystem"
1514import { Log } from "../util/log"
1615import { Protected } from "./protected"
1716import { Ripgrep } from "./ripgrep"
@@ -344,6 +343,7 @@ export namespace File {
344343 Service ,
345344 Effect . gen ( function * ( ) {
346345 const appFs = yield * AppFileSystem . Service
346+ const git = yield * Git . Service
347347
348348 const state = yield * InstanceState . make < State > (
349349 Effect . fn ( "File.state" ) ( ( ) =>
@@ -410,107 +410,98 @@ export namespace File {
410410 cachedScan = yield * Effect . cached ( scan ( ) . pipe ( Effect . catchCause ( ( ) => Effect . void ) ) )
411411 } )
412412
413+ const gitText = Effect . fnUntraced ( function * ( args : string [ ] ) {
414+ return ( yield * git . run ( args , { cwd : Instance . directory } ) ) . text ( )
415+ } )
416+
413417 const init = Effect . fn ( "File.init" ) ( function * ( ) {
414418 yield * ensure ( )
415419 } )
416420
417421 const status = Effect . fn ( "File.status" ) ( function * ( ) {
418422 if ( Instance . project . vcs !== "git" ) return [ ]
419423
420- return yield * Effect . promise ( async ( ) => {
421- const diffOutput = (
422- await Git . run ( [ "-c" , "core.fsmonitor=false" , "-c" , "core.quotepath=false" , "diff" , "--numstat" , "HEAD" ] , {
423- cwd : Instance . directory ,
424+ const diffOutput = yield * gitText ( [
425+ "-c" ,
426+ "core.fsmonitor=false" ,
427+ "-c" ,
428+ "core.quotepath=false" ,
429+ "diff" ,
430+ "--numstat" ,
431+ "HEAD" ,
432+ ] )
433+
434+ const changed : File . Info [ ] = [ ]
435+
436+ if ( diffOutput . trim ( ) ) {
437+ for ( const line of diffOutput . trim ( ) . split ( "\n" ) ) {
438+ const [ added , removed , file ] = line . split ( "\t" )
439+ changed . push ( {
440+ path : file ,
441+ added : added === "-" ? 0 : parseInt ( added , 10 ) ,
442+ removed : removed === "-" ? 0 : parseInt ( removed , 10 ) ,
443+ status : "modified" ,
424444 } )
425- ) . text ( )
426-
427- const changed : File . Info [ ] = [ ]
428-
429- if ( diffOutput . trim ( ) ) {
430- for ( const line of diffOutput . trim ( ) . split ( "\n" ) ) {
431- const [ added , removed , file ] = line . split ( "\t" )
432- changed . push ( {
433- path : file ,
434- added : added === "-" ? 0 : parseInt ( added , 10 ) ,
435- removed : removed === "-" ? 0 : parseInt ( removed , 10 ) ,
436- status : "modified" ,
437- } )
438- }
439445 }
446+ }
440447
441- const untrackedOutput = (
442- await Git . run (
443- [
444- "-c" ,
445- "core.fsmonitor=false" ,
446- "-c" ,
447- "core.quotepath=false" ,
448- "ls-files" ,
449- "--others" ,
450- "--exclude-standard" ,
451- ] ,
452- {
453- cwd : Instance . directory ,
454- } ,
455- )
456- ) . text ( )
457-
458- if ( untrackedOutput . trim ( ) ) {
459- for ( const file of untrackedOutput . trim ( ) . split ( "\n" ) ) {
460- try {
461- const content = await Filesystem . readText ( path . join ( Instance . directory , file ) )
462- changed . push ( {
463- path : file ,
464- added : content . split ( "\n" ) . length ,
465- removed : 0 ,
466- status : "added" ,
467- } )
468- } catch {
469- continue
470- }
471- }
448+ const untrackedOutput = yield * gitText ( [
449+ "-c" ,
450+ "core.fsmonitor=false" ,
451+ "-c" ,
452+ "core.quotepath=false" ,
453+ "ls-files" ,
454+ "--others" ,
455+ "--exclude-standard" ,
456+ ] )
457+
458+ if ( untrackedOutput . trim ( ) ) {
459+ for ( const file of untrackedOutput . trim ( ) . split ( "\n" ) ) {
460+ const content = yield * appFs
461+ . readFileString ( path . join ( Instance . directory , file ) )
462+ . pipe ( Effect . catch ( ( ) => Effect . succeed < string | undefined > ( undefined ) ) )
463+ if ( content === undefined ) continue
464+ changed . push ( {
465+ path : file ,
466+ added : content . split ( "\n" ) . length ,
467+ removed : 0 ,
468+ status : "added" ,
469+ } )
472470 }
471+ }
473472
474- const deletedOutput = (
475- await Git . run (
476- [
477- "-c" ,
478- "core.fsmonitor=false" ,
479- "-c" ,
480- "core.quotepath=false" ,
481- "diff" ,
482- "--name-only" ,
483- "--diff-filter=D" ,
484- "HEAD" ,
485- ] ,
486- {
487- cwd : Instance . directory ,
488- } ,
489- )
490- ) . text ( )
491-
492- if ( deletedOutput . trim ( ) ) {
493- for ( const file of deletedOutput . trim ( ) . split ( "\n" ) ) {
494- changed . push ( {
495- path : file ,
496- added : 0 ,
497- removed : 0 ,
498- status : "deleted" ,
499- } )
500- }
473+ const deletedOutput = yield * gitText ( [
474+ "-c" ,
475+ "core.fsmonitor=false" ,
476+ "-c" ,
477+ "core.quotepath=false" ,
478+ "diff" ,
479+ "--name-only" ,
480+ "--diff-filter=D" ,
481+ "HEAD" ,
482+ ] )
483+
484+ if ( deletedOutput . trim ( ) ) {
485+ for ( const file of deletedOutput . trim ( ) . split ( "\n" ) ) {
486+ changed . push ( {
487+ path : file ,
488+ added : 0 ,
489+ removed : 0 ,
490+ status : "deleted" ,
491+ } )
501492 }
493+ }
502494
503- return changed . map ( ( item ) => {
504- const full = path . isAbsolute ( item . path ) ? item . path : path . join ( Instance . directory , item . path )
505- return {
506- ...item ,
507- path : path . relative ( Instance . directory , full ) ,
508- }
509- } )
495+ return changed . map ( ( item ) => {
496+ const full = path . isAbsolute ( item . path ) ? item . path : path . join ( Instance . directory , item . path )
497+ return {
498+ ...item ,
499+ path : path . relative ( Instance . directory , full ) ,
500+ }
510501 } )
511502 } )
512503
513- const read = Effect . fn ( "File.read" ) ( function * ( file : string ) {
504+ const read : Interface [ "read" ] = Effect . fn ( "File.read" ) ( function * ( file : string ) {
514505 using _ = log . time ( "read" , { file } )
515506 const full = path . join ( Instance . directory , file )
516507
@@ -558,27 +549,19 @@ export namespace File {
558549 )
559550
560551 if ( Instance . project . vcs === "git" ) {
561- return yield * Effect . promise ( async ( ) : Promise < File . Content > => {
562- let diff = (
563- await Git . run ( [ "-c" , "core.fsmonitor=false" , "diff" , "--" , file ] , { cwd : Instance . directory } )
564- ) . text ( )
565- if ( ! diff . trim ( ) ) {
566- diff = (
567- await Git . run ( [ "-c" , "core.fsmonitor=false" , "diff" , "--staged" , "--" , file ] , {
568- cwd : Instance . directory ,
569- } )
570- ) . text ( )
571- }
572- if ( diff . trim ( ) ) {
573- const original = ( await Git . run ( [ "show" , `HEAD:${ file } ` ] , { cwd : Instance . directory } ) ) . text ( )
574- const patch = structuredPatch ( file , file , original , content , "old" , "new" , {
575- context : Infinity ,
576- ignoreWhitespace : true ,
577- } )
578- return { type : "text" , content, patch, diff : formatPatch ( patch ) }
579- }
580- return { type : "text" , content }
581- } )
552+ let diff = yield * gitText ( [ "-c" , "core.fsmonitor=false" , "diff" , "--" , file ] )
553+ if ( ! diff . trim ( ) ) {
554+ diff = yield * gitText ( [ "-c" , "core.fsmonitor=false" , "diff" , "--staged" , "--" , file ] )
555+ }
556+ if ( diff . trim ( ) ) {
557+ const original = yield * git . show ( Instance . directory , "HEAD" , file )
558+ const patch = structuredPatch ( file , file , original , content , "old" , "new" , {
559+ context : Infinity ,
560+ ignoreWhitespace : true ,
561+ } )
562+ return { type : "text" as const , content, patch, diff : formatPatch ( patch ) }
563+ }
564+ return { type : "text" as const , content }
582565 }
583566
584567 return { type : "text" as const , content }
@@ -660,7 +643,7 @@ export namespace File {
660643 } ) ,
661644 )
662645
663- export const defaultLayer = layer . pipe ( Layer . provide ( AppFileSystem . defaultLayer ) )
646+ export const defaultLayer = layer . pipe ( Layer . provide ( AppFileSystem . defaultLayer ) , Layer . provide ( Git . defaultLayer ) )
664647
665648 const { runPromise } = makeRuntime ( Service , defaultLayer )
666649
0 commit comments