Closed
Bug 796953
Opened 12 years ago
Closed 12 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•12 years ago
|
Whiteboard: [mentor=Yoric][lang=js]
Reporter | ||
Comment 1•12 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•12 years ago
|
Assignee: nobody → andres
Assignee | ||
Comment 2•12 years ago
|
||
Local tests are running fine.
Attachment #667729 -
Flags: review?(dteller)
Reporter | ||
Comment 3•12 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•12 years ago
|
||
Updated patch with suggested changes.
Attachment #667729 -
Attachment is obsolete: true
Attachment #668519 -
Flags: review?(dteller)
Reporter | ||
Comment 5•12 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•12 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•12 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•12 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•12 years ago
|
||
Added the suggested change.
Attachment #669268 -
Attachment is obsolete: true
Attachment #669630 -
Flags: review?(dteller)
Reporter | ||
Comment 10•12 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•12 years ago
|
||
Pushed to try: https://tbpl.mozilla.org/?tree=Try&rev=e77e0c7a59a5
Assignee | ||
Comment 12•12 years ago
|
||
Try finished fine with some oranges https://tbpl.mozilla.org/?tree=Try&rev=e77e0c7a59a5
Assignee | ||
Updated•12 years ago
|
Keywords: checkin-needed
Comment 13•12 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/268128a99ac9
Flags: in-testsuite+
Keywords: checkin-needed
Comment 14•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/268128a99ac9
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla19
Updated•11 months ago
|
Product: Toolkit → Toolkit Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•