-
Notifications
You must be signed in to change notification settings - Fork 279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed mozilla/thimble.mozilla.org#1887: File overwrites without notifying user #712
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,15 @@ define(function (require, exports, module) { | |
var Buffer = Filer.Buffer; | ||
var Path = Filer.Path; | ||
var fs = Filer.fs(); | ||
var Dialogs = require("widgets/Dialogs"); | ||
var DefaultDialogs = require("widgets/DefaultDialogs"); | ||
var Strings = require("strings"); | ||
var StringUtils = require("utils/StringUtils"); | ||
|
||
// These are const variables | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Get rid of this comment. |
||
var CANCEL_OPERATION = -1, | ||
OVERWRITE_OPERATION = 1, | ||
KEEP_EXISTING_OPERATION = 2; | ||
|
||
// Mac and Windows clutter zip files with extra files/folders we don't need | ||
function skipFile(filename) { | ||
|
@@ -57,6 +66,49 @@ define(function (require, exports, module) { | |
}); | ||
} | ||
|
||
function showOverwriteWarning(path, callback) { | ||
var filepath = stripRoot(path); | ||
Dialogs.showModalDialog( | ||
DefaultDialogs.DIALOG_ID_INFO, | ||
Strings.FILE_EXISTS_HEADER, | ||
StringUtils.format(Strings.DND_FILE_REPLACE, filepath), | ||
[ | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_NORMAL, | ||
id : Dialogs.DIALOG_BTN_CANCEL, | ||
text : Strings.CANCEL | ||
}, | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_NORMAL, | ||
id : Dialogs.DIALOG_BTN_IMPORT, | ||
text : Strings.USE_IMPORTED | ||
}, | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_PRIMARY, | ||
id : Dialogs.DIALOG_BTN_OK, | ||
text : Strings.KEEP_EXISTING | ||
} | ||
] | ||
).getPromise().then(function (id) { | ||
var result; | ||
if (id === Dialogs.DIALOG_BTN_IMPORT) { | ||
result = OVERWRITE_OPERATION; | ||
} else if (id === Dialogs.DIALOG_BTN_OK) { | ||
result = KEEP_EXISTING_OPERATION; | ||
} else if (id === Dialogs.DIALOG_BTN_CANCEL) { | ||
result = CANCEL_OPERATION; | ||
} | ||
callback(null, result); | ||
}, callback); | ||
} | ||
|
||
function stripRoot(path) { | ||
var root = StartupState.project("root"); | ||
var rootRegex = new RegExp("^" + root + "\/?"); | ||
|
||
return path.replace(rootRegex, ""); | ||
} | ||
|
||
// zipfile can be a path (string) to a zipfile, or raw binary data. | ||
function unzip(zipfile, options, callback) { | ||
if(typeof options === 'function') { | ||
|
@@ -100,21 +152,30 @@ define(function (require, exports, module) { | |
} else { | ||
// XXX: some zip files don't seem to be structured such that dirs | ||
// get created before files. Create base dir if not there yet. | ||
fs.stat(basedir, function(err, stats) { | ||
if(err) { | ||
if(err.code !== "ENOENT") { | ||
return callback(err); | ||
} | ||
|
||
fs.mkdirp(basedir, function(err) { | ||
if(err) { | ||
return callback(err); | ||
} | ||
fs.writeFile(path.absPath, path.data, callback); | ||
}); | ||
} else { | ||
fs.writeFile(path.absPath, path.data, callback); | ||
fs.mkdirp(basedir, function (err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
fs.stat(path.absPath, function(err, stats) { | ||
if(err && err.code !== "ENOENT") { | ||
return callback(err); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too much indent here. |
||
} | ||
if (stats.type === "FILE") { | ||
showOverwriteWarning(path.absPath, function (err, result) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
|
||
if (result === OVERWRITE_OPERATION) { | ||
fs.writeFile(path.absPath, path.data, callback); | ||
} else if (result === KEEP_EXISTING_OPERATION) { | ||
callback(); | ||
} else if (result === CANCEL_OPERATION) { | ||
callback(new Error("Operation Cancelled")); | ||
} | ||
}); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
|
@@ -227,11 +288,33 @@ define(function (require, exports, module) { | |
} | ||
|
||
fs.mkdirp(basedir, function(err) { | ||
if(err && err.code !== "EEXIST") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change? |
||
if(err) { | ||
return callback(err); | ||
} | ||
|
||
fs.writeFile(path, new Buffer(data), {encoding: null}, callback); | ||
fs.stat(path, function (err, stats) { | ||
if (err && err.code !== "ENOENT") { | ||
return callback(err); | ||
} | ||
|
||
if (stats.type !== "FILE") { | ||
return callback(); | ||
} | ||
|
||
showOverwriteWarning(path, function (err, result) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
|
||
if (result === OVERWRITE_OPERATION) { | ||
fs.writeFile(path, new Buffer(data), {encoding: null}, callback); | ||
} else if (result === KEEP_EXISTING_OPERATION) { | ||
return callback(); | ||
} else if (result === CANCEL_OPERATION) { | ||
callback(new Error("Operation Cancelled")); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
|
@@ -244,6 +327,10 @@ define(function (require, exports, module) { | |
|
||
function writeCallback(err) { | ||
if(err) { | ||
if (err.message === "Operation Cancelled") { | ||
finish(err); | ||
return; | ||
} | ||
console.error("[Bramble untar] couldn't extract file", err); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ define(function (require, exports, module) { | |
StringUtils = require("utils/StringUtils"), | ||
Filer = require("filesystem/impls/filer/BracketsFiler"), | ||
Path = Filer.Path, | ||
fs = Filer.fs(), | ||
Content = require("filesystem/impls/filer/lib/content"), | ||
LanguageManager = require("language/LanguageManager"), | ||
StartupState = require("bramble/StartupState"), | ||
|
@@ -134,13 +135,13 @@ define(function (require, exports, module) { | |
}); | ||
} | ||
|
||
function handleRegularFile(deferred, file, filename, buffer, encoding) { | ||
function saveFile(deferred, file, filename, buffer, encoding) { | ||
file.write(buffer, {encoding: encoding}, function(err) { | ||
if (err) { | ||
onError(deferred, filename, err); | ||
return; | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Get rid of this change. |
||
// See if this file is worth trying to open in the editor or not | ||
if(shouldOpenFile(filename, encoding)) { | ||
pathList.push(filename); | ||
|
@@ -150,11 +151,55 @@ define(function (require, exports, module) { | |
}); | ||
} | ||
|
||
function handleRegularFile(deferred, file, filename, buffer, encoding) { | ||
fs.exists(filename, function(doesExist) { | ||
if (doesExist) { | ||
console.log("File: ", filename, " already exists!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove this. |
||
|
||
// File exists. Prompt user for action | ||
Dialogs.showModalDialog( | ||
DefaultDialogs.DIALOG_ID_INFO, | ||
Strings.FILE_EXISTS_HEADER, | ||
StringUtils.format(Strings.DND_FILE_REPLACE, FileUtils.getBaseName(filename)), | ||
[ | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_NORMAL, | ||
id : Dialogs.DIALOG_BTN_CANCEL, | ||
text : Strings.CANCEL | ||
}, | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_NORMAL, | ||
id : Dialogs.DIALOG_BTN_IMPORT, | ||
text : Strings.USE_IMPORTED | ||
}, | ||
{ | ||
className : Dialogs.DIALOG_BTN_CLASS_PRIMARY, | ||
id : Dialogs.DIALOG_BTN_OK, | ||
text : Strings.KEEP_EXISTING | ||
} | ||
] | ||
) | ||
.done(function(id) { | ||
if (id === Dialogs.DIALOG_BTN_IMPORT) { | ||
// Override file per user's request | ||
saveFile(deferred, file, filename, buffer, encoding); | ||
} | ||
}); | ||
} else { | ||
// File doesn't exist. Save without prompt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do this case first, and then return, and then you don't need to indent everything above so much: if (!doesExist) {
// File doesn't exist. Save without prompt
saveFile(deferred, file, filename, buffer, encoding);
return;
}
// rest of code here for other case. |
||
saveFile(deferred, file, filename, buffer, encoding); | ||
} | ||
}); | ||
} | ||
|
||
function handleZipFile(deferred, file, filename, buffer, encoding) { | ||
var basename = Path.basename(filename); | ||
|
||
ArchiveUtils.unzip(buffer, { root: parentPath }, function(err) { | ||
if (err) { | ||
if (err.message === "Operation Cancelled") { | ||
return deferred.resolve(); | ||
} | ||
onError(deferred, filename, new Error(Strings.DND_ERROR_UNZIP)); | ||
return; | ||
} | ||
|
@@ -168,6 +213,9 @@ define(function (require, exports, module) { | |
|
||
ArchiveUtils.untar(buffer, { root: parentPath }, function(err) { | ||
if (err) { | ||
if (err.message === "Operation Cancelled") { | ||
return deferred.resolve(); | ||
} | ||
onError(deferred, filename, new Error(Strings.DND_ERROR_UNTAR)); | ||
return; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -140,7 +140,6 @@ define(function (require, exports, module) { | |
|
||
return Async.doInParallel(paths, function (path, idx) { | ||
var result = new $.Deferred(); | ||
|
||
// Only open files. | ||
FileSystem.resolve(path, function (err, item) { | ||
if (!err && item.isFile) { | ||
|
@@ -182,6 +181,7 @@ define(function (require, exports, module) { | |
return result.promise(); | ||
}, false) | ||
.fail(function () { | ||
console.log("fail"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Revert all the changes in this file. |
||
function errorToString(err) { | ||
if (err === ERR_MULTIPLE_ITEMS_WITH_DIR) { | ||
return Strings.ERROR_MIXED_DRAGDROP; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have all these strings been added to Thimble's repo yet?