-
Notifications
You must be signed in to change notification settings - Fork 337
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
Windows Gitbash Support Fixes #1302 #1475
base: main
Are you sure you want to change the base?
Windows Gitbash Support Fixes #1302 #1475
Conversation
I'm getting time in our next sprint starting next week to dive back in and get reoriented with the requirements of this PR, referencing #1364. I'll be working on other things as well, which is why it's a reorientation task. Also, I need to get familiarized a bit more with rez code and the details of unittesting. I'm optimistic I'll get to start on addressing the notes very soon. |
Thanks for the update @Jawabiscuit ! |
I'm running into a peculiar situation and I'm not sure the best way to resolve it for this PR. Help is appreciated. Here are my notes:
argv = [argv[0]] + [
'rez.tests.test_e2e_shells',
'rez.tests.test_release',
'rez.tests.test_plugin_manager',
'rez.tests.test_shell_utils'
]
main(module=None, argv=argv, verbosity=verbosity) |
Hey @Jawabiscuit , Yeah that
Hm, I think that's because this plugin-manager testcase is loading a fake memory repository from testing data. And when the teardown function doesn't do cleanup,
That said, why it's not falling on CI? EditI think I've got the idea why I did that And in your We should keep in mind that, As for should we do |
Hey @davidlatwe, thanks for responding. Yeah, I'm anticipating there being issues when CI is run in this repo. I'm seeing it come up in my repo https://github.com/Jawabiscuit/rez/actions/runs/4981272972/jobs/8915311256. I'm new with GH actions, for instance I don't know why now it's saying awaiting maintainer approval. It's possible I'm seeing something that might not occur in the ASWF repo but I am able to reproduce it so I thought it's probably worth looking into. I was thinking the same thing about the import for |
That's because we've configured GitHub to not run CI for first time contributors unless we manually approve it. I've been approving the workflows all this time in the background without you noticing. I'm usually pretty quick, but today was a pretty busy day. |
Oh, thanks @JeanChristopheMorinPerso , you were so fast I though it was automated! And sure enough... |
Hehe. I just approved them. FYI, we do this because someone could open PRs to do crypto mining, or just put a super long sleep and it would waste some precious build minutes and it would monopolize the agents. We have access to 100 parallel workflows at the organization level, which means someone could do crypto mining on 100 workers for multiple hours (or until we notice it). So in general, it's better to disable automatic triggers for first time contributors. And I actually think that it's configured like this by default when you create a repo nowadays. |
👋🏼 @Jawabiscuit
Just my 2 cents, I would either directly test with a real shell like this test_shell.py :: test_disabled_path_normalization(), or move that function into
Ah sorry, didn't notice that and no mean to finger-pointing! 🤗 |
JC, cool I have no quams with that. David, thanks, I will do something similar to what you are suggesting. Tangentially, I think this little issue reveals how tests and plugin code are not as isolated as they should could be. In attempts to keep the PR on track, I think if I get the chance I'm feeling inspired to create a discussion to layout a proposal for structural improvements to get some feedback from contributers. I'll look more into if there are similar discussions and through the history of plugins and tests for shells in the meantime. I don't want to spark too much conversation around that subject 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.
I transferred the comments from the previous PRs and added new ones.
src/rez/rezconfig.py
Outdated
# as a result of both the shell and the settings in "pathed_env_vars" and | ||
# "shell_pathed_env_vars". This is meant to aid in debugging and should be | ||
# False unless needed. | ||
disable_normalization = 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.
From what I remember, we initially said we want it to be off by default. So I'd rename it enable_path_normalization
and set the value to False
.
src/rez/rezconfig.py
Outdated
@@ -534,6 +534,19 @@ | |||
"*PATH" | |||
] | |||
|
|||
# Some shells may require multiple types of pathing, so this option provides |
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 feel like this could be clarified and simplified. In its current form, it's kind of hard to understand what it really does.
# Some shells may require multiple types of pathing, so this option provides | ||
# a way to define variables on a per-shell basis to convert for shell pathing | ||
# instead of the pathing provided above or no modification at all. | ||
shell_pathed_env_vars = { |
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.
Maybe env_vars_to_convert or something like that?
src/rez/shells.py
Outdated
@@ -433,7 +472,7 @@ def _create_ex(): | |||
assert self.rcfile_arg | |||
shell_command = "%s %s" % (self.executable, self.rcfile_arg) | |||
else: | |||
shell_command = self.executable | |||
shell_command = '"{}"'.format(self.executable) |
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'm curious, is the double quotes required or it could be single quotes? Single quote are safer because they are not evaluated.
src/rez/tests/test_shell_utils.py
Outdated
def test_path_conversion_mixed(self): | ||
"""Test the path conversion to mixed style.""" | ||
test_path = r'C:\foo\bar\spam' | ||
converted_path = convert_path(test_path, 'unix') |
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.
From @jasoncscott: Isn't this the same test as the previous one? Should it be testing mixed?
@@ -130,13 +143,17 @@ def escape_string(self, value, is_path=False): | |||
if not txt.startswith("'"): | |||
txt = "'%s'" % txt | |||
else: | |||
if is_path: | |||
if is_shell_path: |
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.
What's the difference between a path and a shell path? I'm not sure to understand the difference just by looking at this code and without looking inside the functions that are called.
src/rez/rex.py
Outdated
@@ -571,6 +586,16 @@ def escape_string(self, value, is_path=False): | |||
def _is_pathed_key(cls, key): | |||
return any(fnmatch(key, x) for x in config.pathed_env_vars) | |||
|
|||
@classmethod | |||
def _is_shell_pathed_key(cls, key): | |||
shell_name = cls.name() if hasattr(cls, 'name') else '' |
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.
In which case would name not be present?
src/rez/rex.py
Outdated
@@ -590,13 +615,15 @@ def normalize_path(self, path): | |||
Returns: | |||
str: The normalized path. | |||
""" | |||
print_debug("ActionInterpreter normalize_path()") |
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.
Should these stay or they were purely added for local development purposes?
if config.disable_normalization: | ||
return path | ||
|
||
# TODO: Is this necessary? |
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.
Is it? I personally don't know without taking a deeper look.
src/rezplugins/shell/cmd.py
Outdated
converted_path = convert_path(path, 'windows') | ||
|
||
if path != converted_path: | ||
self._addline("REM normalized path: {!r} -> {}".format(path, converted_path)) |
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.
Should you log too?
993f3e2
to
15ac508
Compare
Hey @JeanChristopheMorinPerso my goal this week is to mark this PR ready for review. I'm finishing up e2e unittests and documentation is the final task on my list. I'll give a thorough breakdown when I change the PR status. That said, we seem to be confronting EoL for python-2 in the images we're using for testing so now the CI is breaking, see also actions/setup-python#672 |
497d526
to
4a21b7a
Compare
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
https://docs.chocolatey.org/en-us/choco/release-notes#breaking-changes Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
…ly fixes the issue in cmd shell. Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
Signed-off-by: javrin <jawabiscuit@users.noreply.github.com>
c8ee458
to
3ff62e9
Compare
Signed-off-by: Jean-Christophe Morin <jean_christophe_morin@hotmail.com>
Signed-off-by: Jean-Christophe Morin <jean_christophe_morin@hotmail.com>
cebfc45
to
1778f57
Compare
I took the liberty to merge the main brain in this PR to make sure that it's up to date. Tests are passing (even with the new refactored CI setup). I had to do some debugging though, and noticed that the |
As requested by @JeanChristopheMorinPerso I'm reposting my comment from #1617 here. I can confirm that the changes introduced in this PR fully address the mentioned issues. But there seems to be a remaining issue utilizing the gitbash shell. (See further down below) Conclusion The error message now provides the path to the exe:
Also setting up a
Rez also is not available in that environment
|
Fixes #1302 by adding gitbash support.
Fixes #1321 with path normalization changes for shells.
Fixed
execute_shell
contexts are being executed with the wrong shell when@per_available_shell()
in unittests. See testing observationssetenv
Changed
/A/b/c
rex paths are normalized to/a/b/c
in Gitbash{root}
orthis.root
{root}
orthis.root
provides the platform normalized canonical pathsourcecode.py
which were too broad and not fixing any issueswarn_shell_startup
to enable shell setting validation and logging warnings or errorsenable_path_normalization
to turn off all normalizationAdds
#!/usr/bin/env bash
style shebangs which are supported in gitbash, and gitbash can execute files with/without file ext much like Unixrezplugins/shell/_utils/windows.py
cygpath.py
anduncpath.py
created to emulatecygpath
cygpath.py
used specifically for gitbash path normalizationshell_pathed_env_vars
, a per-shellpathed_env_vars
settingdebug_shells
to enable debug logging for all shells, includes path normalization messagesdebug_cygpath
to enable debug logging for the cygpath module--py-script-mode
and argument tobind
added, see testing observationsper_available_shell
decorator and to ease testing for a minimal number of available shells, enable use of a small list of included shells per testper_available_shell
decorator with comment to remove if & when normalization is enabled by defaultassertRaisesRegexp
is used and mapped toassertRaisesRegex
for backwards compatibility with Python 2per_available_shell
decorator,execute_shell
would execute the intended shell when it was actually picking up the default system shell every time.as_path
andas_shell_path
rex functions withas_shell_path(pathish, shell=bool)
. No time to implement, but works fine without this feature. I wouldn't mind taking a crack at it in a future PR b/c I do see its benefits.Observations
Testing
rezplugins/shell
likecypath.py
oruncpath.py
causes issues when trying to test. The unittest structure for rez needs to be extended to handle plugin tests so plugin code can be encapsulated. I will break this out into a separate discussion.py
extension depending on the shell. Gitbash supports execution without the extension. For this reason,rez bind
, which installs hello_world in many tests, was updated to support an additional--py-script-mode
via the CLI and an additional argument tobind
on the API side for unittests.default_shell
setting when@per_available_shell()
is used so I modified the decorator to set this setting automatically thereby removing the necessity to state it in most shell tests.Experience
cygpath
to convert paths in build scripts embedded into package defs. This is no longer necessary, which feels more cross-platform capable, however more complicated build scripts outside of a package.py would likely not inherit all the benefits but to what extent remains to be tested.Testing
How to Test/Enable
I recommend using the most recent version of Git for Windows, a backlog of features and fixes was added recently.
Git for Windows 2.41.0 comes with MSYS2 runtime (Git for Windows flavor) with all these improvements based on Cygwin 3.4.6.
The minimum viable settings required to enable gitbash:
Logging Settings
Turn logging on to see normalization in action by setting the appropriate value in your rez config. Messages will print to the terminal as well as in temporary context files.
Path Normalization Settings
These are the most notable settings related to normalization. Please see rezconfig.py for more explicit documentation on each of these settings.
Resolved Context Execution
Here's a table of expected path modifications given the defaults above.
normalize_path
c:\\Users\\jdoe\\src\\...\\packages
/c/Users/jdoe/src/.../packages
normalize_path
c:\\Users\\jdoe\\...\\rez
/c/Users/jdoe/src/.../rez
normalize_path
c:/Users/jdoe/src/.../packages
/c/Users/jdoe/src/.../packages
normalize_path
c:\\Users\\jdoe\\...\\rez
/c/Users/jdoe/src/.../rez
normalize_path
c:\\users\\jdoe\\...\\1.0.0
/c/users/jdoe/src/.../1.0.0
normalize_path
c:\\users\\jdoe\\...\\1.0.0
/c/users/jdoe/src/.../1.0.0
normalize_path
c:\\users\\jdoe\\...\\1.0.0
/c/Users/jdoe/src/.../1.0.0
normalize_path
c:\\users\\jdoe\\...\\1.0.0
/c/Users/jdoe/src/.../1.0.0
as_path
c:\\users\\jdoe\\...\\1.0.0
c:\\users\\jdoe\\...\\1.0.0
normalize_path
c:\\users\\jdoe\\...\\1.0.0
/c/Users/jdoe/src/.../1.0.0
normalize_paths
C:\\Program Files\\git\\bin
${PATH}:/c/Program Files/git/bin
C:\\Python37
${PATH}:/c/Python37
${PATH}:C:\\Windows
${PATH}:/c/Windows
${PATH}:C:\\Windows\\System32
${PATH}:/c/Windows/System32
${PATH}:/mingw64/bin
${PATH}:/mingw64/bin
${PATH}:/usr/bin
${PATH}:/usr/bin
config.rez_1_environment_variables
is set{root}
variant binding, no normalization*PATH
:
Note that rex delegates normalization to the shell (interpreter), calling the appropriate method for the type of path or binding. All paths are normalized to POSIX-style paths, since those are expected when using Gitbash. Gitbash also understands mixed (C:/foo/bar and quoted "C:\foo\bar" paths) but the whole point of using Gitbash is to be able to use posix style paths wherever possible.
Source Code Execution
Now we investigate what we can we expect during execution of the package.py source code which is performed after the "binding and environment setup" steps above.
Given the above code block in
commands()
of a package definition, here's what we can expect.PATH
:
normalize_paths
c:\\users\\jdoe\\src\\...\\1.0.0
/c/users/jdoe/src/.../1.0.0
PYTHONPATH
;
as_shell_path
c:\\users\\jdoe\\src\\...\\1.0.0\\src
c:/users/jdoe/src/.../1.0.0/src
CMAKE_MODULE_PATH
;
as_shell_path
c:\\users\\jdoe\\src\\...\\1.0.0\\cmake
c:/users/jdoe/src/.../1.0.0/cmake
Useful to note here,
PATH
is overridden to use:
since that is what Gitbash expects;;
is used forPYTHONPATH
andCMAKE_MODULE_PATH
due topython
andcmake
being windows native apps that don't care what shell they are running in. Also, there's nothing technically wrong with settingCMAKE_MODULE_PATH
or any other path-like variable in bothenv_var_separators
as well asshell_env_var_separators
, the latter will override the former. It can be assumed that the pathsep forPATH
is usuallyos.pathsep
so that is why it is being overridden for Gitbash in this case.Effects of Normalization for Other Shells
Briefly, environment variables can be designated as "shell pathed" via the
shell_pathed_env_vars
setting but they must also implement any special logic in anas_shell_path
method. Also theas_shell_path
method is only used during execution of the package.py source code. Further customization needs to be handled bynormalize_path
ornormalize_path[s]
methods if necessary.As they are today,
cmd
andpowershell
do not override theiras_shell_path
methods to do anything "special" andnormalize_path
does all the work normalizing paths and converting\
s into/
s. This is for better interoperability with more software like cmake and, unlike Gitbash, there is no need for normalization to be any more complex than that. If for some reason normalization this way becomes an issue thenenable_path_normalization
can be set toFalse
. That should be a very unlikely occurrence since Windows shells have been able to interpret paths with mixed slashes since Windows 7.Please see rezconfig.py for a more verbose explanation of the different ways and settings rez handles path normalization. Below are some examples of what to expect when path normalization is enabled in rez.
Resolved Context Execution
powershell
pwsh
c:\\Users\\jdoe\\src\\package_a
c:/Users/jdoe/src/package_a
powershell
pwsh
\\\\server\\projects\\sw\\dev\\jdoe\\packages
//server/projects/sw/dev/jdoe/packages
Source Code Execution
powershell
pwsh
\\\\server\\projects\\...\\cmake;
\\\\server\\projects\\...\\Modules
//server/projects/.../cmake;
//server/projects/.../Modules
Known Issues
MSYS_NO_PATHCONV=1
seems to have no effect when using gitbash inside a rez-env context. Using that environment variable should inhibit gitbash from converting arguments to windows-style paths. Git for Windows version <=2.41.0 andwinpty
tested.Questions
Related PRs
#1364
🕶 Recommended reading