bower / decompress-zip

Module that decompresses zip files
MIT License
102 stars 76 forks source link

Weird ENOENT bug - Directories not created #29

Closed omnidan closed 9 years ago

omnidan commented 10 years ago

I have a program that extracts something when it starts, later you can clear the extracted folder, download a new archive and re-extract it. Sometimes this re-extraction fails, but it never does when the programs starts.

I kept getting this error:

{ [Error: ENOENT, open '/Users/dan/dev/projects/touchlay/daemon/build/Packages/touchlay/demolauncher/css/app.css']
  errno: 34,
  code: 'ENOENT',
  path: '/Users/dan/dev/projects/touchlay/daemon/build/Packages/touchlay/demolauncher/css/app.css' }

As app.css was yet to be created by the unzipper, I figured that ENOENT in this case means that the css/ folder doesn't exist. So I checked and it didn't. Then I added the following filter:

filter: function (file) {
  if (file.type == 'Directory') mkdirp(package_path + '/' + file.path);
  return true;
}

package_path being /Users/dan/dev/projects/touchlay/daemon/build/Packages/touchlay/demolauncher.

What I don't understand is, why does the library sometimes seem to create the folder and sometimes it doesn't. It might have to do with other code I have in my program so if you need more information just ask.

BCooper63 commented 9 years ago

I ran into this same problem. The root of the issue is that extractors.js has a global array property called cache (line 15). This array is used to cache the directories for which a promise has already been created to ensure that the directories are created only once before the files are extracted.

Because the cache property is in effect a global, when you extract an archive to the same location a second or subsequent time the code does not create new promises for the directory creation because it believes it has already done so. This also leads to a memory leak as the cache will continue to grow as you decompress subsequent archives to different directories.

It seems that ideally the cache would be tied to an instance of the DecompressZip class. That way when the expansion finishes the cache goes away when the DecompressZip instance is freed.

Any chance the maintainers can have a look at this?