Closed
Bug 796953
Opened 13 years ago
Closed 13 years ago
[OS.File] writeAtomic should accept an option noOverwrite
Categories
(Toolkit Graveyard :: OS.File, defect)
Toolkit Graveyard
OS.File
Tracking
(Not tracked)
RESOLVED
FIXED
mozilla19
People
(Reporter: Yoric, Assigned: andreshm)
References
Details
(Whiteboard: [mentor=Yoric][lang=js])
Attachments
(1 file, 3 obsolete files)
11.32 KB,
patch
|
Yoric
:
review+
|
Details | Diff | Splinter Review |
Just as |copy| and |move| accept an option |noOverwrite|, so should |writeAtomic|.
Reporter | ||
Updated•13 years ago
|
Whiteboard: [mentor=Yoric][lang=js]
Reporter | ||
Comment 1•13 years ago
|
||
Should anyone decide to take this as a mentored bug, it requires modifying function |OS.File.writeAtomic|, defined in osfile_shared_front.jsm.
Assignee | ||
Updated•13 years ago
|
Assignee: nobody → andres
Assignee | ||
Comment 2•13 years ago
|
||
Local tests are running fine.
Attachment #667729 -
Flags: review?(dteller)
Reporter | ||
Comment 3•13 years ago
|
||
Comment on attachment 667729 [details] [diff] [review]
Patch v1
Review of attachment 667729 [details] [diff] [review]:
-----------------------------------------------------------------
This looks quite good, thanks. I would like the following changes done, though.
::: toolkit/components/osfile/osfile_async_front.jsm
@@ +627,5 @@
> * - {number} offset The offset in |buffer| at which to start extracting
> * data
> * - {string} tmpPath The path at which to write the temporary file.
> + * - {bool} noOverwrite - If set, this function will fail if a file already
> + * exists at |path|.
You should also document whether |tmpPath| is overwritten if |path| exists.
(also in osfile_shared_front.jsm)
::: toolkit/components/osfile/osfile_shared_front.jsm
@@ +376,5 @@
> + } catch (x) {
> + OS.File.remove(tmpPath);
> + throw x;
> + }
> +
Your code fails at the last possible moment. This is semantically sound but I tend to assume that this is not what users want. So, I would add a check before opening |tmpFile| to fail fast if there is already a file at |path|.
::: toolkit/components/osfile/tests/mochi/main_test_osfile_async.js
@@ +508,5 @@
> test.ok(!(new FileUtils.File(tmpPath).exists()), "Temporary file was removed");
> }
> );
>
> +// Check that writeAtomic fails if noOverwrite is true
... and the destination file already exists!
@@ +512,5 @@
> +// Check that writeAtomic fails if noOverwrite is true
> +
> + promise = promise.then(
> + function check_with_noOverwrite() {
> + options = {tmpPath: tmpPath, bytes: bytes -100, noOverwrite: true};
This looks correct. However, we have slightly changed the recommended style while you were working on this bug. Could you replace this |bytes - 100| with some use of method |.subarray()|? See the latest version of tests for examples.
(same thing in worker_test_osfile_front.js)
@@ +513,5 @@
> +
> + promise = promise.then(
> + function check_with_noOverwrite() {
> + options = {tmpPath: tmpPath, bytes: bytes -100, noOverwrite: true};
> + optionsBackup = {tmpPath: tmpPath, bytes: bytes -100, noOverwrite: true};
I don't think that you actually use |optionsBackup|.
@@ +520,5 @@
> + );
> +
> + promise = promise.then(
> + function onSuccess() {
> + test.fail("With noOverwrite, writeAtomic should have failed");
"should have refused to overwrite file"
@@ +522,5 @@
> + promise = promise.then(
> + function onSuccess() {
> + test.fail("With noOverwrite, writeAtomic should have failed");
> + },
> + function onFailure() {
You could improve the test further by checking the reason of failure and ensure that it is |becauseFileExists|.
@@ +523,5 @@
> + function onSuccess() {
> + test.fail("With noOverwrite, writeAtomic should have failed");
> + },
> + function onFailure() {
> + test.info("With noOverwrite, writeAtomic failure");
"With noOverwrite, writeAtomic correctly failed"
@@ +530,5 @@
> + );
> +
> + promise = promise.then(
> + function compare_complete() {
> + test.info("Compare complete");
"With noOverwrite, writeAtomic correctly did not overwrite destination file"
Attachment #667729 -
Flags: review?(dteller) → feedback+
Assignee | ||
Comment 4•13 years ago
|
||
Updated patch with suggested changes.
Attachment #667729 -
Attachment is obsolete: true
Attachment #668519 -
Flags: review?(dteller)
Reporter | ||
Comment 5•13 years ago
|
||
Comment on attachment 668519 [details] [diff] [review]
Patch v2
Review of attachment 668519 [details] [diff] [review]:
-----------------------------------------------------------------
Patch is good, but we still need to finalize the matter of checking whether a file already exists.
::: toolkit/components/osfile/osfile_shared_front.jsm
@@ +341,5 @@
> + let noOverwrite = options.noOverwrite;
> + if (noOverwrite) {
> + try {
> + // Check if file exists and try to move it to get the error.
> + OS.File.read(path);
|OS.File.read| is a little overkill, as it reads the full contents of the file.
Let me suggest the following:
- introduce a function |OS.File.exists|, which uses |OS.File.open| to determine whether a file can be opened;
- use |OS.File.exists| here;
- in a followup bug, we will see about optimizing |OS.File.exists| using e.g. |access()|
Attachment #668519 -
Flags: review?(dteller) → feedback+
Assignee | ||
Comment 6•13 years ago
|
||
I added the exists method. However, I still need to use the move method to get the 'becauseExists' error.
I tried to do something like throw new OS.File.Error('writeAtomic'), but the 'becauseExists' property is platform specific (Constants.libc.EEXIST or Constants.Win.ERROR_FILE_EXISTS).
> if (noOverwrite && OS.File.exists(path)) {
> // Try to move the file to get the appropiate file exists error.
> OS.File.move(tmpPath, path, {noCopy: true, noOverwrite: true});
> }
In the follow up bug I will create the tests for the exists method.
Attachment #668519 -
Attachment is obsolete: true
Attachment #669268 -
Flags: review?(dteller)
Reporter | ||
Comment 7•13 years ago
|
||
Comment on attachment 669268 [details] [diff] [review]
Patch v3
Review of attachment 669268 [details] [diff] [review]:
-----------------------------------------------------------------
::: toolkit/components/osfile/osfile_shared_front.jsm
@@ +356,5 @@
> }
> +
> + let noOverwrite = options.noOverwrite;
> + if (noOverwrite && OS.File.exists(path)) {
> + // Try to move the file to get the appropiate file exists error.
Ok, I see why you do this, but this is too much of a hack :)
The right solution is... to complicate things (again) by introducing a function |OS.File.Error.exists()|, along the lines of |OS.File.Error.closed()|. See the end of files osfile_win_allthreads.jsm and osfile_unix_allthreads.jsm.
Attachment #669268 -
Flags: review?(dteller) → feedback+
Reporter | ||
Comment 8•13 years ago
|
||
(In reply to Andres Hernandez [:andreshm] from comment #6)
> Created attachment 669268 [details] [diff] [review]
> Patch v3
>
> I added the exists method. However, I still need to use the move method to
> get the 'becauseExists' error.
> I tried to do something like throw new OS.File.Error('writeAtomic'), but the
> 'becauseExists' property is platform specific (Constants.libc.EEXIST or
> Constants.Win.ERROR_FILE_EXISTS).
Yes, I encountered this issue for reporting that a file is closed, which lead me to define OS.File.Error.closed. See osfile_{win, unix}_allthreads.jsm . You will need to do the same.
> In the follow up bug I will create the tests for the exists method.
Sounds good.
Assignee | ||
Comment 9•13 years ago
|
||
Added the suggested change.
Attachment #669268 -
Attachment is obsolete: true
Attachment #669630 -
Flags: review?(dteller)
Reporter | ||
Comment 10•13 years ago
|
||
Comment on attachment 669630 [details] [diff] [review]
Patch v4
Review of attachment 669630 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good.
You have my r+ (assuming tests pass, of course).
Attachment #669630 -
Flags: review?(dteller) → review+
Assignee | ||
Comment 11•13 years ago
|
||
Pushed to try: https://tbpl.mozilla.org/?tree=Try&rev=e77e0c7a59a5
Assignee | ||
Comment 12•13 years ago
|
||
Try finished fine with some oranges https://tbpl.mozilla.org/?tree=Try&rev=e77e0c7a59a5
Assignee | ||
Updated•13 years ago
|
Keywords: checkin-needed
Comment 13•13 years ago
|
||
Flags: in-testsuite+
Keywords: checkin-needed
Comment 14•13 years ago
|
||
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla19
Updated•2 years ago
|
Product: Toolkit → Toolkit Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•