-
-
Notifications
You must be signed in to change notification settings - Fork 185
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add ability to show unified diffs for changed files #562
base: master
Are you sure you want to change the base?
Conversation
The now() template builtin is being used in the test and is an alias for datetime.utcnow(). The now however, just uses datetime.now(). This means that my datetime.now() will always make this test fail. Signed-off-by: David Stanek <dstanek@dstanek.com>
Signed-off-by: David Stanek <dstanek@dstanek.com>
I'm still working on this, but I wanted to get the idea out there. |
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 tricky part are updates, they apply some diff without asking.
Line 705 in e4eccc2
(apply_cmd << diff)(retcode=None) |
Gotta do something about that, but anyways that's already a problem, so this won't make it worse.
some code comments too.
very nice addition, thanks!
copier/tools.py
Outdated
elif line.startswith("-"): | ||
color_print(colorama.Fore.RED, f"{indent}{line}") | ||
elif line.startswith("+"): | ||
color_print(colorama.Fore.GREEN, f"{indent}{line}") |
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.
https://python-prompt-toolkit.readthedocs.io/en/master/pages/printing_text.html#pygments-token-text-tuples with a diff lexer should save a lot of code around here.
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 I was going down this path first, but it seemed very difficult to get the result I wanted. I went ahead and finished that work a put together a gist showing the differences. orig.diff
is the code from this PR and new.diff
uses pygments
and prompt_toolkit
.
One reason the new code is much larger is that I wanted to have the two-line file header yellow like it is with git. This meant that I had to extend the lexer. In order to add the extra indentation, I had to also extend the PygmentsTokens
class to inject whitespace. There may be better ways to accomplish these tasks, but I'm never had to dip into the bowels of these libraries before.
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 see.
Well, I'll have to do local testing for both implementations, because code looks complex in both cases, so if we're getting a complexity, I'll get the one that looks/works better 😄
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'll update this implementation here since that's what I'm actively using and I think I can make it cleaner and more concise. If you like the other way better I can switch to that later.
copier/tools.py
Outdated
|
||
|
||
def color_print(color: int, msg: str): | ||
print(f"{color}{msg}{colorama.Fore.RESET}") |
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.
You have https://python-prompt-toolkit.readthedocs.io/en/master/pages/printing_text.html#html and https://plumbum.readthedocs.io/en/latest/colors.html for printing colorized output. You probably won't need this function.
@@ -144,6 +151,7 @@ class Worker: | |||
overwrite: bool = False | |||
pretend: bool = False | |||
quiet: bool = False | |||
diff: bool = False |
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 is a nice addition. I don't think it's needed to add a new flag for 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.
Just default to always diff when we can?
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 can't imagine a use case where the no diff is more useful if we're on interactive mode.
Codecov Report
@@ Coverage Diff @@
## master #562 +/- ##
==========================================
- Coverage 96.29% 95.32% -0.98%
==========================================
Files 41 41
Lines 2701 2737 +36
==========================================
+ Hits 2601 2609 +8
- Misses 100 128 +28
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
copier/tools.py
Outdated
try: | ||
original_lines = get_lines(original_content) | ||
except Exception: | ||
color_print( | ||
colorama.Fore.YELLOW, "diff unavailable: unable to determine encoding" | ||
) | ||
return | ||
try: | ||
new_lines = get_lines(new_content) | ||
except Exception: | ||
color_print( | ||
colorama.Fore.YELLOW, "diff unavailable: unable to determine encoding" | ||
) | ||
return |
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 know some flake8 plugins would say: "only one line in a try block", but this could probably be factorized as:
try: | |
original_lines = get_lines(original_content) | |
except Exception: | |
color_print( | |
colorama.Fore.YELLOW, "diff unavailable: unable to determine encoding" | |
) | |
return | |
try: | |
new_lines = get_lines(new_content) | |
except Exception: | |
color_print( | |
colorama.Fore.YELLOW, "diff unavailable: unable to determine encoding" | |
) | |
return | |
try: | |
original_lines = get_lines(original_content) | |
new_lines = get_lines(new_content) | |
except Exception: | |
color_print( | |
colorama.Fore.YELLOW, "diff unavailable: unable to determine encoding" | |
) | |
return |
Also, is there a reason you catch Exception
rather than the more specific UnicodeDecodeError
?
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 could combine the try blocks.
The reason I'm currently catching Exception is mostly because this isn't ready to merge. My first version used chardet
and there were some exceptions to catch, then I decided to do a "detect on the cheap" algorithm to avoid an extra dependency and finally settled on hard coding utf-8 once I realized that Jinja is already doing that. If the final version is just the single decode then I could switch to catch that one exception.
Since the previous implementations had a few exceptions to catch and there is no particular handing for any of them I just went with Exception.
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 see, thanks!
Hi folks! This was stiill under my radar, although quite deferred because it needs some testing and deep analyzing. However, recently we got #627 which proposes to remove I'd love to hear your opinions. |
I'll take a look at that in more detail, but it doesn't seem related to this PR. In this PR I wanted the ability do what Ansible calls "check mode." The ability to run a command and see what would change if it were to be applied. Just a little background on my use case. I have a set of a few dozen microservices (likely to keep growing) that are based on the same configuration files and general structure. I want to convert it to use copier as the base for management. New services would use copier to start off. With this feature, we could make changes to our base configuration repo (say a logging format change) and have an easy way for a service owner to see what is different without creating new files. We could also run this over all services to see which is out of sync (run a weekly report from CICD like dependabot). |
Signed-off-by: David Stanek dstanek@dstanek.com