1
0
mirror of https://github.com/deadc0de6/dotdrop.git synced 2026-02-05 12:03:49 +00:00

Use alternative list-based diff_cmd escaping

The previous escaping method of wrapping the arguments with double
quotes would eventually fail in some cases, since Linux allows pretty
much any character for a filename.

Using a different quoting character, like the single quote would have
brought you back to the exact same issue. As soon as any part of the
path contained your escape quote character, the code would break.

The code would use `shlex`, a parser for Linux shells. However, this
wasn't working since even that wouldn't know where your argument began
and ended, since it wasn't escaped properly. Meaning, a string like:

`diff -r /home/test/.config/Code - OSS/t"t't.test mytestfile.test`

Would then break any of the quoting solutions. And shlex, since it
wouldn't know where arguments start and end, it would think an
argument ends at `home/test/.config/Code`, since the spaces haven't
been escaped. But escaping the spaces with quote characters is not a
good idea since any parts of the path with those quote arguments would
then again break shlex and it wouldn't be able to tell when your
argument starts and ends.

The solution for that is to, before we replace our diff template
string with the given files arguments, we can just split it by
whitespace, and manually replace the `{0}` and `{1}` placeholders.
This allows us to keep the separation with a Python list. What does
this mean? That when you then call `subprocess.Popen` with this list,
`subprocess` knows where all your arguments start and end, even if
they themselves are not properly escaped. But since it's all split in
a list, `subprocess` has a concept of what is a single argument and
would apply the needed escaping to each individual argument.
This commit is contained in:
Sighery
2020-01-26 12:28:28 +01:00
parent 40a9872f56
commit 704f8deab6
2 changed files with 12 additions and 5 deletions

View File

@@ -49,7 +49,7 @@ class Settings(DictParser):
upignore=[], cmpignore=[], instignore=[],
workdir='~/.config/dotdrop', showdiff=False,
minversion=None, func_file=[], filter_file=[],
diff_command='diff -r "{0}" "{1}"'):
diff_command='diff -r {0} {1}'):
self.backup = backup
self.banner = banner
self.create = create

View File

@@ -71,12 +71,19 @@ def shell(cmd, debug=False):
def diff(original, modified, raw=True,
diff_cmd='diff -r "{0}" "{1}"', debug=False):
diff_cmd='diff -r {0} {1}', debug=False):
"""compare two files"""
if not diff_cmd:
diff_cmd = 'diff -r "{0}" "{1}"'
cmd = diff_cmd.format(original, modified)
_, out = run(shlex.split(cmd), raw=raw, debug=debug)
diff_cmd = 'diff -r {0} {1}'
replacements = {
"{0}": original,
"{original}": original,
"{1}": modified,
"{modified}": modified,
}
cmd = [replacements.get(x, x) for x in diff_cmd.split()]
_, out = run(cmd, raw=raw, debug=debug)
return out