enhance(diff): add plain view for long line files - #39202
Conversation
Add a "View plain diff" button when a file contains lines that exceed the configured rendering limit. The button opens the complete Git patch for that file as plain text in a new tab, without syntax highlighting. The link adds `plain=true` to existing diff URLs. The commit, comparison, and pull-request handlers then stream the selected patch as text/plain, reusing the existing files parameters to identify the file, including both paths of a rename. Plain requests validate that selection and pass the names to Git literally (using `--literal-pathspecs`) so they cannot expand to unrelated files. The existing rendered-diff limits and repository access checks remain unchanged. Tests were added to exercise the new behavior.
|
Why it needs to introduce more workarounds? Can you increase your |
|
It's not really a work-around. As long as there's a limit, there will be cases in which you can't currently view the diff at all. And removing the limit entirely would mean being susceptible to DOS attacks, since the parser ( |
|
I'd like to be able to view any kind of diff in the browser via gitea. This PR makes that possible.
You can, but this has usability and performance implications that this PR does not. Doing what you suggest means 1) figuring what the max line size will ever be on my server, or changing it if a new max line length appears, and 2) paying the memory cost associated with that max line setting even when it's extremely rare. The latter is because // OK let's set a reasonable buffer size.
// This should be at least the size of maxLineCharacters or 4096 whichever is larger.
readerSize := max(maxLineCharacters, 4096)This PR has neither of those drawbacks: you can keep the max line length to something reasonable while, in the rare case that you do get some absurdly long line length, still being able to view the diff.
Maybe? Either the plain diff makes the change really obvious, in which case yes, or it doesn't, so you open it up in a better tool that helps you review it. But for either case to happen, you need some way to know what the diff is at all. and this PR give you that. Otherwise, there are just diffs that gitea gives you absolutely no way to view at all, without pulling whatever the diff refers to locally. |
Do you have a real world use case? For example: what kind of file has more than 10000 or 20000 chars in one line to diff and need to be reviewed? At least, it need to clarify the use case and leave comments for it. |
|
This happened when I had a file with one minified line (javascript) embedded in otherwise normal changes. I wanted to review the other changes at a glance before dropping in to an editor that could un-minify the line. |
Then such diff result usually is useless because a huge line is changed. You can simply click the "View file" menu item to open the file and have a full view (review). So I still don't think it is a real world use case or it's worth to make the code base and logic more complicated than it should be. |
If you'd like to review other short lines, the best UI/UX is to render all the short lines, only ignore the long line. Then end users can see the diff result at first glance, no need to click the "load" button. So the render logic can be changed to this:
Haven't looked into details, I guess it is feasible and brings better user experience. |
|
I agree, that would be nicer. I did consider it, but it seemed like a must harder change than the one proposed here. Still, I'm happy to investigate if that's your preference. |
Thank you. TBH I guess it is easier than "reload the raw diff". I also found that IsIncompleteLineTooLong was never tested, so it's also a good chance to remove it, and only mark long lines as incomplete (per line). The new logic can be covered by a unit test in I will also take a look later. |

Add a "View plain diff" button when a file contains lines that exceed the configured rendering limit. The button opens the complete Git patch for that file as plain text in a new tab, without syntax highlighting.
The link adds
plain=trueto existing diff URLs. The commit, comparison, and pull-request handlers then stream the selected patch as text/plain, reusing the existing files parameters to identify the file, including both paths of a rename. Plain requests validate that selection and pass the names to Git literally (using--literal-pathspecs) so they cannot expand to unrelated files.The existing rendered-diff limits and repository access checks remain unchanged. Tests were added to exercise the new behavior.