@@ -4,6 +4,7 @@ import stream from "node:stream";
4
4
5
5
import tar from "tar" ;
6
6
import yauzl from "yauzl-promise" ;
7
+ import { ensureSymlink } from "fs-extra" ;
7
8
8
9
/**
9
10
* Decompresses a file at `filePath` to `cacheDir` directory.
@@ -32,19 +33,61 @@ export default async function decompress(filePath, cacheDir) {
32
33
* @return {Promise<void> }
33
34
*/
34
35
export async function unzip ( zippedFile , cacheDir ) {
36
+ await unzipInternal ( zippedFile , cacheDir , false ) . then ( ( ) => {
37
+ unzipInternal ( zippedFile , cacheDir , true ) ;
38
+ } )
39
+ }
40
+
41
+ /**
42
+ * Method for unzip with symlink in theoretical
43
+ *
44
+ * @async
45
+ * @function
46
+ * @param unzipSymlink
47
+ * @param {string } zippedFile - file path to .zip file
48
+ * @param {string } cacheDir - directory to unzip in
49
+ * @param {boolean } unzipSymlink - Using or not symlink
50
+ * @return {Promise<void> }
51
+ */
52
+ async function unzipInternal ( zippedFile , cacheDir , unzipSymlink ) {
35
53
const zip = await yauzl . open ( zippedFile ) ;
36
54
37
55
let entry = await zip . readEntry ( ) ;
38
56
39
57
while ( entry !== null ) {
58
+ // console.log(entry)
40
59
let entryPathAbs = path . join ( cacheDir , entry . filename ) ;
41
-
42
60
// Create the directory beforehand to prevent `ENOENT: no such file or directory` errors.
43
- await fs . promises . mkdir ( path . dirname ( entryPathAbs ) , { recursive : true } ) ;
44
-
61
+ await fs . promises . mkdir ( path . dirname ( entryPathAbs ) , { recursive : true } ) ;
45
62
const readStream = await entry . openReadStream ( ) ;
46
- const writeStream = fs . createWriteStream ( entryPathAbs ) ;
47
- await stream . promises . pipeline ( readStream , writeStream ) ;
63
+
64
+ try {
65
+ if ( ! unzipSymlink ) {
66
+ // Regular method and silent error at this point
67
+ const writeStream = fs . createWriteStream ( entryPathAbs ) ;
68
+ await stream . promises . pipeline ( readStream , writeStream ) ;
69
+ } else {
70
+ // Need check before if file is a symlink or not at this point
71
+ const pathContent = await fs . promises . lstat ( entryPathAbs ) ;
72
+
73
+ if ( pathContent . isSymbolicLink ( ) ) {
74
+ const chunks = [ ] ;
75
+ readStream . on ( 'data' , ( chunk ) => chunks . push ( chunk ) ) ;
76
+ await stream . promises . finished ( readStream ) ;
77
+ // need fetch value of current symlink here
78
+ const linkTarget = Buffer . concat ( chunks ) . toString ( 'utf8' ) . trim ( ) ;
79
+ await ensureSymlink ( entryPathAbs , path . join ( path . dirname ( entryPathAbs ) , linkTarget ) ) ;
80
+ } else {
81
+ // Regular method and silent error at this point
82
+ const writeStream = fs . createWriteStream ( entryPathAbs ) ;
83
+ await stream . promises . pipeline ( readStream , writeStream ) ;
84
+ }
85
+ }
86
+ } catch ( error ) {
87
+ if ( unzipSymlink ) {
88
+ console . error ( error ) ;
89
+ }
90
+ }
48
91
49
92
entry = await zip . readEntry ( ) ;
50
93
}
0 commit comments