Handle new, changed and deleted symlinks in git.
Review Request #8785 — Created Feb. 28, 2017 and submitted
Mark up file diffs that add, change or remove a symlink so that a label can be shown in the UI to indicate that the file is a symlink. Also normalize a git patch containing a symlink to make the file appear as a regular file, otherwise patch fails to apply the diff, complaining about the file not being a symlink.
Unit test.
Tested with a patch adding a symlink and changing another symlink. The files
were properly marked with " (symlink)" in the UI.
Description | From | Last Updated |
---|---|---|
Since this won't necessarily be in extra_data, you'll need to change this to filediff.extra_data.get('symlink') or False. |
chipx86 | |
While here, mind splitting this across a few lines, like: filediff.extra_data = { 'symlink': f.symlink, } That'll make it easier … |
chipx86 | |
Good cleanup. For memory savings, let's use tuples instead of lists here. |
chipx86 | |
This will be a bit cheaper and more readable if you do: attr_value = info.get(attr) if isinstance(attr_value, six.binary_type): attr_value = … |
chipx86 | |
Not part of your change, but mind reversing these while you're here? Ordering is wrong. |
chipx86 | |
This will need to use our modern docstring format, which would look like: ```python """Normalize the provided patch file. This … |
chipx86 | |
Blank line between these. We also use m for regex match variable names. |
chipx86 | |
I think this would be cleaner with only one return statement: m = ... if m: mode = ... if … |
chipx86 | |
Blank line here. |
chipx86 | |
Single quotes for the string. Also, can you use format strings for the entire thing here: patch = b'%s%o%s' % … |
chipx86 | |
We don't use the if .. else form in our code, instead opting to be more verbose. In this case, … |
chipx86 | |
Thanks for all the unit tests! Much appreciated :) Can you modify the other tests to assertFalse(f.symlink), so that we … |
chipx86 | |
E222 multiple spaces after operator |
reviewbot | |
F821 undefined name 'match' |
reviewbot | |
F821 undefined name 'match' |
reviewbot | |
This should have a trailing comma after. That makes it cleaner to add new content without modifying this line. |
chipx86 | |
Can you rename this to FILE_MODE_RE? |
chipx86 |
- Change Summary:
-
New draft that besides normalizing the patch so that it can be applied, also marks the symlink as such in the UI.
- Summary:
-
Make new and deleted symlinks in git look like regular filesHandle new, changed and deleted symlinks in git
- Description:
-
~ Otherwise patch fails to apply the diff, complaining about the file not being a
~ symlink. ~ Mark up file diffs that add, change or remove a symlink so that a label can be
~ shown in the UI to indicate that the file is a symlink. + + Also normalize a git patch containing a symlink to make the file appear as a
+ regular file, otherwise patch fails to apply the diff, complaining about the + file not being a symlink. - Testing Done:
-
~ Tested with patch containing removed symlink, added symlink and replaced symlink.
~ Unit test.
+ + Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in th UI.
- Commit:
-
67b9499f9e139576a81e69ff67ba739859c7aea3a356bedeb8d26b014c00f18acc8f39f85dbb536c
Checks run (2 succeeded, 1 failed with error)
- Commit:
-
a356bedeb8d26b014c00f18acc8f39f85dbb536c77b51e19b430438a2faedb1896c17f16d805fb9e
Checks run (2 succeeded, 1 failed with error)
-
Thank you for your patience and gentle prodding. Let's get this change in!
I have a handful of nits, mostly around our coding/doc standards and some alternative ways parts can be written. The overall approach seems sound to me, though.
-
Since this won't necessarily be in
extra_data
, you'll need to change this tofilediff.extra_data.get('symlink') or False
. -
While here, mind splitting this across a few lines, like:
filediff.extra_data = { 'symlink': f.symlink, }
That'll make it easier to add to things later.
Also, mind changing the name (here and in other places) to
is_symlink
? Our older metadata doesn't do this, but it would allow us to reservesymlink
for additional details, if we end up with a use for that from some SCM. -
-
This will be a bit cheaper and more readable if you do:
attr_value = info.get(attr) if isinstance(attr_value, six.binary_type): attr_value = attr_value.decode('utf-8') setattr(file, attr, attr_value)
-
-
This will need to use our modern docstring format, which would look like:
```python
"""Normalize the provided patch file.This will make new, changed, and deleted symlinks ...
...
Args:
patch (bytes):
The patch data being posted for review.filename (unicode): The name of the file being modified. revision (unicode): The revision of the file being modified.
Returns:
bytes:
The normalized patch data.
""" -
-
I think this would be cleaner with only one return statement:
m = ... if m: mode = ... if stat.S_ISLNK(mode): mode = ... patch = patch[...] + ... return patch
-
-
Single quotes for the string.
Also, can you use format strings for the entire thing here:
patch = b'%s%o%s' % (patch[...], mode, patch[...])
That will ensure we have a bytestring at the end, and is more efficient than concatenating.
-
We don't use the
if .. else
form in our code, instead opting to be more verbose. In this case, it's not really needed, since we don't even want to performstat.S_ISLNK
if it doesn't match. You can write this as:m = ...search(line) if m: mode = int(m.group('mode'), 8) if stat.S_ISLNK(mode): file_info.symlink = True break
-
Thanks for all the unit tests! Much appreciated :)
Can you modify the other tests to
assertFalse(f.symlink)
, so that we can verify (now and going forward) that the flag isn't accidentally set?
- Change Summary:
-
Fixed most of Christian's comments. Haven't tested it yet though (except for unit tests) as I couldn't get the test env up and running. Will try again later.
- Testing Done:
-
Unit test.
~ Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in th UI.
~ (TODO: perform test with latest code) Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in the UI.
- Commit:
-
77b51e19b430438a2faedb1896c17f16d805fb9e64d4fdb83db852fe2d6d4806d26e92fdb9cc5340
- Change Summary:
-
Fix typos.
- Commit:
-
64d4fdb83db852fe2d6d4806d26e92fdb9cc5340868b63cf201e5e3bb446649cdd1e31b90c39519b
Checks run (2 succeeded)
- Change Summary:
-
Fixed a bug where all files got the symlink status of the first file.
- Testing Done:
-
Unit test.
~ (TODO: perform test with latest code) Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in the UI.
~ Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in the UI.
- Commit:
-
868b63cf201e5e3bb446649cdd1e31b90c39519b9b3ca256b6b5366988ecf0c80f5f1fb9130b5870
Checks run (2 succeeded)
- Summary:
-
Handle new, changed and deleted symlinks in gitHandle new, changed and deleted symlinks in git.
- Testing Done:
-
Unit test.
~ Tested with a patch adding a symlink and changing another symlink. The files were properly marked with " (symlink)" in the UI.
~ Tested with a patch adding a symlink and changing another symlink. The files
+ were properly marked with " (symlink)" in the UI.