Throw clearer error when 'storage' is a broken symlink
Instead of '(NS_ERROR_FILE_ALREADY_EXISTS) [nsIFile.create]', throw "Broken symlink at <path>". Closes #1834
This commit is contained in:
		
					parent
					
						
							
								83cdbd8e5c
							
						
					
				
			
			
				commit
				
					
						8614e73aa8
					
				
			
		
					 2 changed files with 74 additions and 7 deletions
				
			
		| 
						 | 
					@ -984,24 +984,59 @@ Zotero.File = new function(){
 | 
				
			||||||
	this.createDirectoryIfMissing = function (dir) {
 | 
						this.createDirectoryIfMissing = function (dir) {
 | 
				
			||||||
		dir = this.pathToFile(dir);
 | 
							dir = this.pathToFile(dir);
 | 
				
			||||||
		if (!dir.exists() || !dir.isDirectory()) {
 | 
							if (!dir.exists() || !dir.isDirectory()) {
 | 
				
			||||||
			if (dir.exists() && !dir.isDirectory()) {
 | 
								if (dir.exists()) {
 | 
				
			||||||
				dir.remove(null);
 | 
									if (!dir.isDirectory()) {
 | 
				
			||||||
 | 
										dir.remove(null);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									let isSymlink = false;
 | 
				
			||||||
 | 
									// isSymlink() fails if the directory doesn't exist, but is true if it's a broken
 | 
				
			||||||
 | 
									// symlink, in which case exists() returns false
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										isSymlink = dir.isSymlink();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									catch (e) {}
 | 
				
			||||||
 | 
									if (isSymlink) {
 | 
				
			||||||
 | 
										throw new Error(`Broken symlink at ${dir.path}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755);
 | 
								dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0o755);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	this.createDirectoryIfMissingAsync = function (path) {
 | 
						this.createDirectoryIfMissingAsync = async function (path) {
 | 
				
			||||||
		return Zotero.Promise.resolve(
 | 
							try {
 | 
				
			||||||
			OS.File.makeDir(
 | 
								await OS.File.makeDir(
 | 
				
			||||||
				path,
 | 
									path,
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					ignoreExisting: true,
 | 
										ignoreExisting: false,
 | 
				
			||||||
					unixMode: 0o755
 | 
										unixMode: 0o755
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		);
 | 
							}
 | 
				
			||||||
 | 
							catch (e) {
 | 
				
			||||||
 | 
								// If there's a broken symlink at the given path, makeDir() will throw becauseExists,
 | 
				
			||||||
 | 
								// but exists() will return false
 | 
				
			||||||
 | 
								if (e.becauseExists) {
 | 
				
			||||||
 | 
									if (await OS.File.exists(path)) {
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									let isSymlink = false;
 | 
				
			||||||
 | 
									// Confirm with nsIFile that it's a symlink
 | 
				
			||||||
 | 
									try {
 | 
				
			||||||
 | 
										isSymlink = this.pathToFile(path).isSymlink();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									catch (e) {
 | 
				
			||||||
 | 
										Zotero.logError(e);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (isSymlink) {
 | 
				
			||||||
 | 
										throw new Error(`Broken symlink at ${path}`);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								throw e;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,6 +239,38 @@ describe("Zotero.File", function () {
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						describe("#createDirectoryIfMissing()", function () {
 | 
				
			||||||
 | 
							it("should throw error on broken symlink", async function () {
 | 
				
			||||||
 | 
								if (Zotero.isWin) {
 | 
				
			||||||
 | 
									this.skip();
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var tmpPath = await getTempDirectory();
 | 
				
			||||||
 | 
								var destPath = OS.Path.join(tmpPath, 'missing');
 | 
				
			||||||
 | 
								var linkPath = OS.Path.join(tmpPath, 'link');
 | 
				
			||||||
 | 
								await OS.File.unixSymLink(destPath, linkPath);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								assert.throws(() => Zotero.File.createDirectoryIfMissing(linkPath), /^Broken symlink/);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						describe("#createDirectoryIfMissingAsync()", function () {
 | 
				
			||||||
 | 
							it("should throw error on broken symlink", async function () {
 | 
				
			||||||
 | 
								if (Zotero.isWin) {
 | 
				
			||||||
 | 
									this.skip();
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var tmpPath = await getTempDirectory();
 | 
				
			||||||
 | 
								var destPath = OS.Path.join(tmpPath, 'missing');
 | 
				
			||||||
 | 
								var linkPath = OS.Path.join(tmpPath, 'link');
 | 
				
			||||||
 | 
								await OS.File.unixSymLink(destPath, linkPath);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var e = await getPromiseError(Zotero.File.createDirectoryIfMissingAsync(linkPath));
 | 
				
			||||||
 | 
								assert.ok(e);
 | 
				
			||||||
 | 
								assert.match(e.message, /^Broken symlink/);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	describe("#zipDirectory()", function () {
 | 
						describe("#zipDirectory()", function () {
 | 
				
			||||||
		it("should compress a directory recursively", function* () {
 | 
							it("should compress a directory recursively", function* () {
 | 
				
			||||||
			var tmpPath = Zotero.getTempDirectory().path;
 | 
								var tmpPath = Zotero.getTempDirectory().path;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue