@@ -58,7 +58,9 @@ import type { Logger } from './logger'
58
58
import type { TransformPlugin } from './transform/types'
59
59
60
60
interface fs {
61
- stat : ( filePath : string ) => Promise < { mtimeMs : bigint } >
61
+ stat : (
62
+ filePath : string ,
63
+ ) => Promise < { mtimeMs : bigint ; mode : number ; uid : number ; gid : number } >
62
64
mkdtempSync : ( prefix : string ) => string
63
65
rename : ( oldPath : string , newPath : string ) => Promise < void >
64
66
writeFile : ( filePath : string , content : string ) => Promise < void >
@@ -67,10 +69,20 @@ interface fs {
67
69
) => Promise <
68
70
{ stat : { mtimeMs : bigint } ; fileContent : string } | 'file-not-existing'
69
71
>
72
+ chmod : ( filePath : string , mode : number ) => Promise < void >
73
+ chown : ( filePath : string , uid : number , gid : number ) => Promise < void >
70
74
}
71
75
72
76
const DefaultFileSystem : fs = {
73
- stat : ( filePath ) => fsp . stat ( filePath , { bigint : true } ) ,
77
+ stat : async ( filePath ) => {
78
+ const res = await fsp . stat ( filePath , { bigint : true } )
79
+ return {
80
+ mtimeMs : res . mtimeMs ,
81
+ mode : Number ( res . mode ) ,
82
+ uid : Number ( res . uid ) ,
83
+ gid : Number ( res . gid ) ,
84
+ }
85
+ } ,
74
86
mkdtempSync : mkdtempSync ,
75
87
rename : ( oldPath , newPath ) => fsp . rename ( oldPath , newPath ) ,
76
88
writeFile : ( filePath , content ) => fsp . writeFile ( filePath , content ) ,
@@ -90,6 +102,8 @@ const DefaultFileSystem: fs = {
90
102
throw e
91
103
}
92
104
} ,
105
+ chmod : ( filePath , mode ) => fsp . chmod ( filePath , mode ) ,
106
+ chown : ( filePath , uid , gid ) => fsp . chown ( filePath , uid , gid ) ,
93
107
}
94
108
95
109
interface Rerun {
@@ -1031,6 +1045,31 @@ ${acc.routeTree.map((child) => `${child.variableName}${exportName}: typeof ${get
1031
1045
event : { type : 'update' , path : opts . filePath } ,
1032
1046
} )
1033
1047
}
1048
+ const newFileState = await this . fs . stat ( tmpPath )
1049
+ if ( newFileState . mode !== beforeStat . mode ) {
1050
+ await this . fs . chmod ( tmpPath , beforeStat . mode )
1051
+ }
1052
+ if (
1053
+ newFileState . uid !== beforeStat . uid ||
1054
+ newFileState . gid !== beforeStat . gid
1055
+ ) {
1056
+ try {
1057
+ await this . fs . chown ( tmpPath , beforeStat . uid , beforeStat . gid )
1058
+ } catch ( err ) {
1059
+ if (
1060
+ typeof err === 'object' &&
1061
+ err !== null &&
1062
+ 'code' in err &&
1063
+ ( err as any ) . code === 'EPERM'
1064
+ ) {
1065
+ console . warn (
1066
+ `[safeFileWrite] chown failed: ${ ( err as any ) . message } ` ,
1067
+ )
1068
+ } else {
1069
+ throw err
1070
+ }
1071
+ }
1072
+ }
1034
1073
} else {
1035
1074
if ( await checkFileExists ( opts . filePath ) ) {
1036
1075
throw rerun ( {
0 commit comments