78
78
79
79
final class VirtualFileSystemImpl implements FileSystem , AutoCloseable {
80
80
81
- static final String VFS_ROOT = "org.graalvm.python.vfs" ;
82
- static final String VFS_FILESLIST = "fileslist.txt" ;
81
+ /*
82
+ * Root of the virtual filesystem in the resources.
83
+ */
84
+ static final String VFS_ROOT = "/org.graalvm.python.vfs" ;
85
+
83
86
static final String VFS_HOME = "home" ;
84
87
static final String VFS_VENV = "venv" ;
85
88
static final String VFS_PROJ = "proj" ;
86
89
static final String VFS_SRC = "src" ;
87
90
88
- private static final String VENV_PREFIX = "/" + VFS_ROOT + "/" + VFS_VENV ;
89
- private static final String HOME_PREFIX = "/" + VFS_ROOT + "/" + VFS_HOME ;
90
- private static final String PROJ_PREFIX = "/" + VFS_ROOT + "/" + VFS_PROJ ;
91
- private static final String SRC_PREFIX = "/" + VFS_ROOT + "/" + VFS_SRC ;
91
+ /*
92
+ * Index of all files and directories available in the resources at runtime. - paths are
93
+ * absolute - directory paths end with a '/' - uses '/' separator regardless of platform. Used
94
+ * to determine directory entries, if an entry is a file or a directory, etc.
95
+ */
96
+ private static final String FILES_LIST_PATH = VFS_ROOT + "/fileslist.txt" ;
97
+
98
+ private static final String VENV_PREFIX = VFS_ROOT + "/" + VFS_VENV ;
99
+ private static final String HOME_PREFIX = VFS_ROOT + "/" + VFS_HOME ;
100
+ private static final String PROJ_PREFIX = VFS_ROOT + "/" + VFS_PROJ ;
101
+ private static final String SRC_PREFIX = VFS_ROOT + "/" + VFS_SRC ;
92
102
private boolean extractOnStartup = "true" .equals (System .getProperty ("graalpy.vfs.extractOnStartup" ));
93
103
94
104
public static enum HostIO {
@@ -97,18 +107,6 @@ public static enum HostIO {
97
107
READ_WRITE ,
98
108
}
99
109
100
- /*
101
- * Root of the virtual filesystem in the resources.
102
- */
103
- private final String vfsPrefix ;
104
-
105
- /*
106
- * Index of all files and directories available in the resources at runtime. - paths are
107
- * absolute - directory paths end with a '/' - uses '/' separator regardless of platform. Used
108
- * to determine directory entries, if an entry is a file or a directory, etc.
109
- */
110
- private final String filesListPath ;
111
-
112
110
/*
113
111
* Maps platform-specific paths to entries.
114
112
*/
@@ -241,8 +239,6 @@ private void removeExtractDir() {
241
239
} else {
242
240
this .resourceLoadingClass = VirtualFileSystemImpl .class ;
243
241
}
244
- this .vfsPrefix = "/" + VirtualFileSystemImpl .VFS_ROOT ;
245
- this .filesListPath = vfsPrefix + "/" + VirtualFileSystemImpl .VFS_FILESLIST ;
246
242
247
243
this .caseInsensitive = caseInsensitive ;
248
244
String mp = System .getenv ("GRAALPY_VFS_MOUNT_POINT" );
@@ -302,8 +298,8 @@ String vfsVenvPath() {
302
298
}
303
299
304
300
private String resourcePathToPlatformPath (String inputPath ) {
305
- assert inputPath .length () > vfsPrefix .length () && inputPath .startsWith (vfsPrefix ) : "inputPath expected to start with '" + vfsPrefix + "' but was '" + inputPath + "'" ;
306
- var path = inputPath .substring (vfsPrefix .length () + 1 );
301
+ assert inputPath .length () > VFS_ROOT .length () && inputPath .startsWith (VFS_ROOT ) : "inputPath expected to start with '" + VFS_ROOT + "' but was '" + inputPath + "'" ;
302
+ var path = inputPath .substring (VFS_ROOT .length () + 1 );
307
303
if (!PLATFORM_SEPARATOR .equals (RESOURCE_SEPARATOR )) {
308
304
path = path .replace (RESOURCE_SEPARATOR , PLATFORM_SEPARATOR );
309
305
}
@@ -327,7 +323,7 @@ private String platformPathToResourcePath(String inputPath) {
327
323
if (path .endsWith (RESOURCE_SEPARATOR )) {
328
324
path = path .substring (0 , path .length () - RESOURCE_SEPARATOR .length ());
329
325
}
330
- path = vfsPrefix + path ;
326
+ path = VFS_ROOT + path ;
331
327
return path ;
332
328
}
333
329
@@ -337,7 +333,7 @@ private String toCaseComparable(String file) {
337
333
338
334
private void initEntries () throws IOException {
339
335
vfsEntries = new HashMap <>();
340
- try (InputStream stream = this .resourceLoadingClass .getResourceAsStream (filesListPath )) {
336
+ try (InputStream stream = this .resourceLoadingClass .getResourceAsStream (FILES_LIST_PATH )) {
341
337
if (stream == null ) {
342
338
return ;
343
339
}
@@ -506,6 +502,30 @@ private void extract(Path path) throws IOException {
506
502
}
507
503
}
508
504
505
+ public void extractResources (Path destRootDir ) throws IOException {
506
+ InputStream stream = this .resourceLoadingClass .getResourceAsStream (FILES_LIST_PATH );
507
+ if (stream == null ) {
508
+ return ;
509
+ }
510
+ BufferedReader br = new BufferedReader (new InputStreamReader (stream ));
511
+ String resourcePath ;
512
+ while ((resourcePath = br .readLine ()) != null ) {
513
+ Path destFile = destRootDir .resolve (Path .of (resourcePath .substring (VFS_ROOT .length () + 1 )));
514
+ if (destFile == null ) {
515
+ continue ;
516
+ }
517
+ if (resourcePath .endsWith (RESOURCE_SEPARATOR )) {
518
+ Files .createDirectories (destFile );
519
+ } else {
520
+ Path parent = destFile .getParent ();
521
+ if (parent != null ) {
522
+ Files .createDirectories (parent );
523
+ }
524
+ Files .write (destFile , readResource (resourcePath ));
525
+ }
526
+ }
527
+ }
528
+
509
529
@ Override
510
530
public Path parsePath (URI uri ) {
511
531
if (uri .getScheme ().equals ("file" )) {
0 commit comments