@@ -17,6 +17,12 @@ type RecordedCommand = {
1717 readonly args : ReadonlyArray < string >
1818}
1919
20+ type ProcessPatch = {
21+ readonly prevProjectsRoot : string | undefined
22+ readonly prevStdinTty : boolean | undefined
23+ readonly prevStdoutTty : boolean | undefined
24+ }
25+
2026const withTempDir = < A , E , R > (
2127 use : ( tempDir : string ) => Effect . Effect < A , E , R >
2228) : Effect . Effect < A , E , R | FileSystem . FileSystem > =>
@@ -32,6 +38,40 @@ const withTempDir = <A, E, R>(
3238 } )
3339 )
3440
41+ const patchProcessForInteractiveSsh = ( projectsRoot : string ) : Effect . Effect < ProcessPatch , never > =>
42+ Effect . sync ( ( ) => {
43+ const prevProjectsRoot = process . env [ "DOCKER_GIT_PROJECTS_ROOT" ]
44+ const prevStdinTty = process . stdin . isTTY
45+ const prevStdoutTty = process . stdout . isTTY
46+
47+ process . env [ "DOCKER_GIT_PROJECTS_ROOT" ] = projectsRoot
48+ Object . defineProperty ( process . stdin , "isTTY" , { value : true , configurable : true } )
49+ Object . defineProperty ( process . stdout , "isTTY" , { value : true , configurable : true } )
50+
51+ return { prevProjectsRoot, prevStdinTty, prevStdoutTty }
52+ } )
53+
54+ const restorePatchedProcess = ( patch : ProcessPatch ) : Effect . Effect < void , never > =>
55+ Effect . sync ( ( ) => {
56+ if ( patch . prevProjectsRoot === undefined ) {
57+ delete process . env [ "DOCKER_GIT_PROJECTS_ROOT" ]
58+ } else {
59+ process . env [ "DOCKER_GIT_PROJECTS_ROOT" ] = patch . prevProjectsRoot
60+ }
61+ Object . defineProperty ( process . stdin , "isTTY" , { value : patch . prevStdinTty , configurable : true } )
62+ Object . defineProperty ( process . stdout , "isTTY" , { value : patch . prevStdoutTty , configurable : true } )
63+ } )
64+
65+ const withInteractiveProcess = < A , E , R > (
66+ projectsRoot : string ,
67+ use : Effect . Effect < A , E , R >
68+ ) : Effect . Effect < A , E , R > =>
69+ Effect . scoped (
70+ Effect . acquireRelease ( patchProcessForInteractiveSsh ( projectsRoot ) , restorePatchedProcess ) . pipe (
71+ Effect . flatMap ( ( ) => use )
72+ )
73+ )
74+
3575const encode = ( value : string ) : Uint8Array => new TextEncoder ( ) . encode ( value )
3676
3777const commandIncludes = ( args : ReadonlyArray < string > , needle : string ) : boolean => args . includes ( needle )
@@ -140,25 +180,12 @@ describe("createProject (openSsh)", () => {
140180 const executor = makeFakeExecutor ( recorded )
141181 const command = makeCommand ( root , outDir , path )
142182
143- const prevProjectsRoot = process . env [ "DOCKER_GIT_PROJECTS_ROOT" ]
144- const prevStdinTty = process . stdin . isTTY
145- const prevStdoutTty = process . stdout . isTTY
146-
147- process . env [ "DOCKER_GIT_PROJECTS_ROOT" ] = path . join ( root , "state" )
148- Object . defineProperty ( process . stdin , "isTTY" , { value : true , configurable : true } )
149- Object . defineProperty ( process . stdout , "isTTY" , { value : true , configurable : true } )
150-
151- try {
152- yield * _ ( createProject ( command ) . pipe ( Effect . provideService ( CommandExecutor . CommandExecutor , executor ) ) )
153- } finally {
154- if ( prevProjectsRoot === undefined ) {
155- delete process . env [ "DOCKER_GIT_PROJECTS_ROOT" ]
156- } else {
157- process . env [ "DOCKER_GIT_PROJECTS_ROOT" ] = prevProjectsRoot
158- }
159- Object . defineProperty ( process . stdin , "isTTY" , { value : prevStdinTty , configurable : true } )
160- Object . defineProperty ( process . stdout , "isTTY" , { value : prevStdoutTty , configurable : true } )
161- }
183+ yield * _ (
184+ withInteractiveProcess (
185+ path . join ( root , "state" ) ,
186+ createProject ( command ) . pipe ( Effect . provideService ( CommandExecutor . CommandExecutor , executor ) )
187+ )
188+ )
162189
163190 const sshInvocations = recorded . filter ( ( entry ) => entry . command === "ssh" )
164191 expect ( sshInvocations ) . toHaveLength ( 1 )
0 commit comments