From 704f8deab6ac872b35699fc910a3a61ed66c4522 Mon Sep 17 00:00:00 2001 From: Sighery Date: Sun, 26 Jan 2020 12:28:28 +0100 Subject: [PATCH 1/2] 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. --- dotdrop/settings.py | 2 +- dotdrop/utils.py | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/dotdrop/settings.py b/dotdrop/settings.py index 0bef2b3..bfc3ae6 100644 --- a/dotdrop/settings.py +++ b/dotdrop/settings.py @@ -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 diff --git a/dotdrop/utils.py b/dotdrop/utils.py index df073e6..1842d30 100644 --- a/dotdrop/utils.py +++ b/dotdrop/utils.py @@ -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 From 99150cec8887fd50b34c4a65d0b4911a890f7937 Mon Sep 17 00:00:00 2001 From: deadc0de6 Date: Sun, 26 Jan 2020 19:37:52 +0100 Subject: [PATCH 2/2] remove "import shlex" to pass tests --- dotdrop/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dotdrop/utils.py b/dotdrop/utils.py index 1842d30..689b4db 100644 --- a/dotdrop/utils.py +++ b/dotdrop/utils.py @@ -9,7 +9,6 @@ import subprocess import tempfile import os import uuid -import shlex import fnmatch import inspect import importlib