Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Filesystem] Add appendToFile()#20612
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
95aec8b to0e207b0Comparero0NL commentedNov 26, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
We could also go with |
chalasr commentedNov 26, 2016
@ro0NL We could and it would make sense imho. Though I'm comfortable with what is proposed here because it's something I actually needed a lot of times, I have concrete use cases for it. |
nicolas-grekas commentedDec 12, 2016
The implementation looks very fragile to me: it's not atomic at all; why should it fail when the file doesn't exist? |
chalasr commentedDec 12, 2016
You're right, it should not fail by default, but I think it should be opt-in for cases where the content must not be appended if the file doesn't already exist.
To ease error handling as Given the whole |
5bef77b to35d33faComparechalasr commentedDec 16, 2016
Removed the exception when the file doesn't exist. Now this behaves like |
88a308c tofc87aa0Compare| } | ||
| $tmpFile =$this->tempnam(dirname($filename),basename($filename)); | ||
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.
What about forwarding todumpFile instead in this case? So above checks can be removed..
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.
Nice catch, done 👍
fc87aa0 to35eb1cbCompare| */ | ||
| publicfunctionappendToFile($filename,$content) | ||
| { | ||
| if (false !==$originalContent = @file_get_contents($filename)) { |
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.
$content = $originalContent.$content;
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.
Oops! thanks@ro0NL
| if (false !==$originalContent = @file_get_contents($filename)) { | ||
| $originalContent =''; | ||
| } | ||
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.
$filename, $content
c185ecd toec7c144Comparechalasr commentedDec 18, 2016
Travis failure is unrelated |
| * @throws IOException If the file is not writable | ||
| */ | ||
| publicfunctionappendToFile($filename,$content) | ||
| { |
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.
This now loads the current file content into memory (which doesn't look like an atomic append to me). Wouldn't it be better to rely on theFILE_APPEND flag offile_put_contents instead?
You could refactor a bit the logic insidedumpFile in order to extract it in a private method adding the flag or not.
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.
which doesn't look like an atomic append to me
The write is atomic, usingfile_put_contents for the read operation would not make it more atomic to me, do I miss something?
You could refactor a bit the logic inside dumpFile in order to extract it in a private method adding the flag or not.
It was my first intention, but would you avoid creating a tmpfile for append? Otherwise we still have to usefile_get_contents or doing twofile_put_contents,
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.
We could doFILE_APPEND|LOCK_EX. Basically creating the tmp file is about forcing an exclusive lock right?
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.
We could do FILE_APPEND|LOCK_EX
Yeah, I was about to propose it :)
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.
Im not an filesystem expert.. but the tmp file in the middle feels like a poor man solution to me.. so perhapsLOCK_EX is the way to go indeed fordumpeFile as well.
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.
using file_put_contents for the read operation would not make it more atomic to me
Never told you to do so ^^'
We could do FILE_APPEND|LOCK_EX
That's basically what I meant.
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.
So what about a publicwriteFile($filename, $content[, $append = false]) then? UsingLOCK_EX by design and letdumpFile forward? That to me would be the simplest implementation.
But a private function in the middle allowing this API (appendToFile anddumpFile) is also fine 👍 i guess.
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.
Updated
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.
In fact, usingLOCK_EX doesn't makefile_put_contents atomic, so in both cases (usingfile_get_contents/file_put_contents orfile_put_contents with flags) the append would not be atomic. Considering this I prefer to letdumpFile() as it is since the behavior is better (maybe not really atomic, but more than usingfile_put_contents directly).
Refs:
#10018 (comment)
http://stackoverflow.com/questions/4899737/should-lock-ex-on-both-read-write-be-atomic
AboutappendToFile, I'm still not sure what is better between usingfile_get_contents orfile_put_contents with FILE_APPEND, but I tend to prefer usingfile_get_contents to avoid havingfile_put_contents breaks in the middle of the write..
| * Atomically dumps content into a file. | ||
| * | ||
| * @param string $filename The file to be written to | ||
| * @param string $content The data to write into the file |
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.
For usingfile_put_contents we technically allowstring|array|resource.
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.
I agree, updated on the two newly added methods.
Since this targets master, would you mind to open a PR against 2.8 (it doesn't handle streams in 2.7, see0fc513e) for changing this docblock? I think it's worth it
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.
Agree.
ec7c144 to9908df7Compareogizanagi commentedDec 18, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
👍 We just need to validate there isn't any downside about using Status: Reviewed |
9908df7 to2e21cf5Compare286de84 to86fe81aCompare5681f39 to4e737b4Compare| { | ||
| $dir =dirname($filename); | ||
| if (!is_dir($dir)) { |
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.
Don't we have to check here too that the directory is writable after we created it (the directory might have been created by another process)?
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.
Indeed, done. The same could be applied ondumpFile() I think
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.
Yes, I think you are right. Should be done on2.7 then as bug fix IMO.
4e737b4 to9fb4050Compare| /** | ||
| * Appends content to an existing file. | ||
| * |
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.
The file to which to append content
xabbuh commentedJan 8, 2017
👍 |
9fb4050 to0e52144Compare…d it in dumpFile() (chalasr)This PR was merged into the 2.7 branch.Discussion----------[Filesystem] Check that directory is writable after created it in dumpFile()| Q | A| ------------- | ---| Branch? | 2.7| Bug fix? | yes| New feature? | no| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets |#20612 (comment)| License | MIT| Doc PR | n/aIn case permissions have been changed meanwhileCommits-------dbc4148 [Filesystem] Check that the directory is writable after created it in dumpFile()
| * | ||
| * @param string $filename The file to which to append content | ||
| * @param string $content The content to append | ||
| * |
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.
If you remove the capital letter above, you should do the same here, right?
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.
Reverted the removal of the capital letter
0e52144 to9fb5293Comparefabpot commentedJan 8, 2017
Can you add a note in the CHANGELOG? |
9fb5293 to1f7b753Comparechalasr commentedJan 8, 2017
CHANGELOG updated |
fabpot commentedJan 8, 2017
Thank you@chalasr. |
This PR was merged into the 3.3-dev branch.Discussion----------[Filesystem] Add appendToFile()| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | n/a| License | MIT| Doc PR | todoSo we could append content to a file:```php(new Filesystem)->appendToFile($file, 'bar');```instead of doing it in two steps:```phpif (false === $content = @file_get_contents($file)) { throw new \Exception();}(new Filesystem)->dumpFile($file, $content.'bar');```Doing it opt-in using `dumpFile(..., $append = false)` would have been enough but not possible for BC.Commits-------9fb5293 [Filesystem] Add appendToFile()This PR was merged into the 3.3-dev branch.Discussion----------[Filesystem] Add appendToFile()| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets | n/a| License | MIT| Doc PR | todoSo we could append content to a file:```php(new Filesystem)->appendToFile($file, 'bar');```instead of doing it in two steps:```phpif (false === $content = @file_get_contents($file)) { throw new \Exception();}(new Filesystem)->dumpFile($file, $content.'bar');```Doing it opt-in using `dumpFile(..., $append = false)` would have been enough but not possible for BC.Commits-------1f7b753 [Filesystem] Add appendToFile()javiereguiluz commentedJan 8, 2017
I'm super late to this but I wonder if this method should be called |
ogizanagi commentedJan 8, 2017
I'm fine with the But that's only my 2 cents :) |
chalasr commentedJan 8, 2017
@javiereguiluz I hesitated for |
chalasr commentedJan 8, 2017
@fabpot I think there is something wrong with your git tool, commits are merged twice, see the master log |
ogizanagi commentedJan 8, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Commits' contents aren't even the same... 😅 Also, the merge commit date is before the merge itself 😆 |
Uh oh!
There was an error while loading.Please reload this page.
So we could append content to a file:
instead of doing it in two steps:
Doing it opt-in using
dumpFile(..., $append = false)would have been enough but not possible for BC.