Skip to content

Commit e35ca88

Browse files
sdalmeidahumphd
authored andcommitted
Added warning if imported file overwrites local files.
1 parent 3ad1010 commit e35ca88

3 files changed

Lines changed: 158 additions & 23 deletions

File tree

src/filesystem/impls/filer/ArchiveUtils.js

Lines changed: 107 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ define(function (require, exports, module) {
1818
var Buffer = Filer.Buffer;
1919
var Path = Filer.Path;
2020
var fs = Filer.fs();
21+
var Dialogs = require("widgets/Dialogs");
22+
var DefaultDialogs = require("widgets/DefaultDialogs");
23+
var Strings = require("strings");
24+
var StringUtils = require("utils/StringUtils");
25+
26+
var CANCEL_OPERATION = -1,
27+
OVERWRITE_OPERATION = 1,
28+
KEEP_EXISTING_OPERATION = 2;
2129

2230
// Mac and Windows clutter zip files with extra files/folders we don't need
2331
function skipFile(filename) {
@@ -56,6 +64,48 @@ define(function (require, exports, module) {
5664
CommandManager.execute(Commands.FILE_REFRESH).always(callback);
5765
}
5866

67+
function showOverwriteWarning(path, callback) {
68+
var filepath = stripRoot(path);
69+
70+
Dialogs.showModalDialog(
71+
DefaultDialogs.DIALOG_ID_INFO,
72+
Strings.FILE_EXISTS_HEADER,
73+
StringUtils.format(Strings.DND_FILE_REPLACE, filepath),
74+
[{
75+
className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
76+
id : Dialogs.DIALOG_BTN_CANCEL,
77+
text : Strings.CANCEL
78+
},
79+
{
80+
className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
81+
id : Dialogs.DIALOG_BTN_IMPORT,
82+
text : Strings.USE_IMPORTED
83+
},
84+
{
85+
className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
86+
id : Dialogs.DIALOG_BTN_OK,
87+
text : Strings.KEEP_EXISTING
88+
}]
89+
).getPromise().then(function (id) {
90+
var result;
91+
if (id === Dialogs.DIALOG_BTN_IMPORT) {
92+
result = OVERWRITE_OPERATION;
93+
} else if (id === Dialogs.DIALOG_BTN_OK) {
94+
result = KEEP_EXISTING_OPERATION;
95+
} else if (id === Dialogs.DIALOG_BTN_CANCEL) {
96+
result = CANCEL_OPERATION;
97+
}
98+
callback(null, result);
99+
}, callback);
100+
}
101+
102+
function stripRoot(path) {
103+
var root = StartupState.project("root");
104+
var rootRegex = new RegExp("^" + root + "\/?");
105+
106+
return path.replace(rootRegex, "");
107+
}
108+
59109
// zipfile can be a path (string) to a zipfile, or raw binary data.
60110
function unzip(zipfile, options, callback) {
61111
var projectPrefix = StartupState.project("zipFilenamePrefix").replace(/\/?$/, "/");
@@ -105,28 +155,42 @@ define(function (require, exports, module) {
105155
var basedir = Path.dirname(path.absPath);
106156

107157
if(path.isDirectory) {
108-
fs.mkdirp(path.absPath, callback);
109-
} else {
110-
// XXX: some zip files don't seem to be structured such that dirs
111-
// get created before files. Create base dir if not there yet.
112-
fs.stat(basedir, function(err, stats) {
113-
if(err) {
114-
if(err.code !== "ENOENT") {
158+
return fs.mkdirp(path.absPath, callback);
159+
}
160+
161+
// XXX: some zip files don't seem to be structured such that dirs
162+
// get created before files. Create base dir if not there yet.
163+
fs.mkdirp(basedir, function (err) {
164+
if (err) {
165+
return callback(err);
166+
}
167+
168+
fs.stat(path.absPath, function(err, stats) {
169+
if(err && err.code !== "ENOENT") {
170+
return callback(err);
171+
}
172+
173+
if (stats.type !== "FILE") {
174+
return callback();
175+
}
176+
177+
showOverwriteWarning(path.absPath, function (err, result) {
178+
if (err) {
115179
return callback(err);
116180
}
117181

118-
fs.mkdirp(basedir, function(err) {
119-
if(err) {
120-
return callback(err);
121-
}
122-
182+
if (result === OVERWRITE_OPERATION) {
123183
FilerUtils.writeFileAsBinary(path.absPath, path.data, callback);
124-
});
125-
} else {
126-
FilerUtils.writeFileAsBinary(path.absPath, path.data, callback);
127-
}
184+
} else if (result === KEEP_EXISTING_OPERATION) {
185+
callback();
186+
} else if (result === CANCEL_OPERATION) {
187+
callback(new Error("Operation Cancelled"));
188+
} else {
189+
callback(new Error("Unknown result: " + result));
190+
}
191+
});
128192
});
129-
}
193+
});
130194
}
131195

132196
async.eachSeries(filenames, decompress, function(err) {
@@ -245,11 +309,35 @@ define(function (require, exports, module) {
245309
}
246310

247311
fs.mkdirp(basedir, function(err) {
248-
if(err && err.code !== "EEXIST") {
312+
if(err) {
249313
return callback(err);
250314
}
251315

252-
FilerUtils.writeFileAsBinary(path, new Buffer(data), callback);
316+
fs.stat(path, function (err, stats) {
317+
if (err && err.code !== "ENOENT") {
318+
return callback(err);
319+
}
320+
321+
if (stats.type !== "FILE") {
322+
return callback();
323+
}
324+
325+
showOverwriteWarning(path, function (err, result) {
326+
if (err) {
327+
return callback(err);
328+
}
329+
330+
if (result === OVERWRITE_OPERATION) {
331+
FilerUtils.writeFileAsBinary(path, new Buffer(data), callback);
332+
} else if (result === KEEP_EXISTING_OPERATION) {
333+
callback();
334+
} else if (result === CANCEL_OPERATION) {
335+
callback(new Error("Operation Cancelled"));
336+
} else {
337+
callback(new Error("Unknown result: " + result));
338+
}
339+
});
340+
});
253341
});
254342
}
255343

src/filesystem/impls/filer/lib/WebKitFileImport.js

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ define(function (require, exports, module) {
3737
Strings = require("strings"),
3838
Filer = require("filesystem/impls/filer/BracketsFiler"),
3939
Path = Filer.Path,
40+
fs = Filer.fs(),
4041
Content = require("filesystem/impls/filer/lib/content"),
4142
ArchiveUtils = require("filesystem/impls/filer/ArchiveUtils");
4243

@@ -125,13 +126,13 @@ define(function (require, exports, module) {
125126
});
126127
}
127128

128-
function handleRegularFile(deferred, file, filename, buffer, encoding) {
129+
function saveFile(deferred, file, filename, buffer, encoding) {
129130
file.write(buffer, {encoding: encoding}, function(err) {
130131
if (err) {
131132
onError(deferred, filename, err);
132133
return;
133134
}
134-
135+
135136
// See if this file is worth trying to open in the editor or not
136137
if(shouldOpenFile(filename, encoding)) {
137138
pathList.push(filename);
@@ -141,11 +142,55 @@ define(function (require, exports, module) {
141142
});
142143
}
143144

145+
function handleRegularFile(deferred, file, filename, buffer, encoding) {
146+
fs.exists(filename, function(doesExist) {
147+
if (doesExist) {
148+
console.log("File: ", filename, " already exists!");
149+
150+
// File exists. Prompt user for action
151+
Dialogs.showModalDialog(
152+
DefaultDialogs.DIALOG_ID_INFO,
153+
Strings.FILE_EXISTS_HEADER,
154+
StringUtils.format(Strings.DND_FILE_REPLACE, FileUtils.getBaseName(filename)),
155+
[
156+
{
157+
className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
158+
id : Dialogs.DIALOG_BTN_CANCEL,
159+
text : Strings.CANCEL
160+
},
161+
{
162+
className : Dialogs.DIALOG_BTN_CLASS_NORMAL,
163+
id : Dialogs.DIALOG_BTN_IMPORT,
164+
text : Strings.USE_IMPORTED
165+
},
166+
{
167+
className : Dialogs.DIALOG_BTN_CLASS_PRIMARY,
168+
id : Dialogs.DIALOG_BTN_OK,
169+
text : Strings.KEEP_EXISTING
170+
}
171+
]
172+
)
173+
.done(function(id) {
174+
if (id === Dialogs.DIALOG_BTN_IMPORT) {
175+
// Override file per user's request
176+
saveFile(deferred, file, filename, buffer, encoding);
177+
}
178+
});
179+
} else {
180+
// File doesn't exist. Save without prompt
181+
saveFile(deferred, file, filename, buffer, encoding);
182+
}
183+
});
184+
}
185+
144186
function handleZipFile(deferred, file, filename, buffer, encoding) {
145187
var basename = Path.basename(filename);
146188

147189
ArchiveUtils.unzip(buffer, { root: parentPath }, function(err) {
148190
if (err) {
191+
if (err.message === "Operation Cancelled") {
192+
return deferred.resolve();
193+
}
149194
onError(deferred, filename, new Error(Strings.DND_ERROR_UNZIP));
150195
return;
151196
}
@@ -159,6 +204,9 @@ define(function (require, exports, module) {
159204

160205
ArchiveUtils.untar(buffer, { root: parentPath }, function(err) {
161206
if (err) {
207+
if (err.message === "Operation Cancelled") {
208+
return deferred.resolve();
209+
}
162210
onError(deferred, filename, new Error(Strings.DND_ERROR_UNTAR));
163211
return;
164212
}

src/utils/DragAndDrop.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ define(function (require, exports, module) {
4848
// this is the path they want to use as a parent dir root.
4949
var _dropPathHint;
5050

51-
5251
/**
5352
* Returns true if the drag and drop items contains valid drop objects.
5453
* @param {Array.<DataTransferItem>} items Array of items being dragged
@@ -142,7 +141,6 @@ define(function (require, exports, module) {
142141

143142
return Async.doInParallel(paths, function (path, idx) {
144143
var result = new $.Deferred();
145-
146144
// Only open files.
147145
FileSystem.resolve(path, function (err, item) {
148146
if (!err && item.isFile) {
@@ -184,6 +182,7 @@ define(function (require, exports, module) {
184182
return result.promise();
185183
}, false)
186184
.fail(function () {
185+
console.log("fail");
187186
function errorToString(err) {
188187
if (err === ERR_MULTIPLE_ITEMS_WITH_DIR) {
189188
return Strings.ERROR_MIXED_DRAGDROP;

0 commit comments

Comments
 (0)