summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddhant Kumar <skumar619@bloomberg.net>2020-08-23 14:25:50 +0100
committerGitHub <noreply@github.com>2020-08-23 14:25:50 +0100
commit6c098d8daa3ed2b34723b62eef9411bded6460b0 (patch)
treed236bacf2c552ab96eca8d34328e914973d281fb
parent7de4f3f904746cbdc31a4bc764d5adfcfb3c61e5 (diff)
downloadvirtualenv-6c098d8daa3ed2b34723b62eef9411bded6460b0.tar.gz
Use unix line-endings in bash activate script (#1924)
Co-authored-by: Bernat Gabor <bgabor8@bloomberg.net>
-rw-r--r--.gitattributes4
-rw-r--r--docs/changelog/1818.bugfix.rst1
-rw-r--r--src/virtualenv/activation/powershell/activate.ps1120
-rw-r--r--src/virtualenv/activation/via_template.py12
-rw-r--r--src/virtualenv/create/via_global_ref/api.py5
-rw-r--r--src/virtualenv/util/path/_pathlib/via_os_path.py7
-rw-r--r--tests/unit/activation/conftest.py11
-rw-r--r--tests/unit/activation/test_bash.py5
-rw-r--r--tests/unit/activation/test_batch.py1
-rw-r--r--tests/unit/activation/test_python_activator.py3
10 files changed, 96 insertions, 73 deletions
diff --git a/.gitattributes b/.gitattributes
index 69b47b5..c925e26 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,5 @@
*.bat text eol=crlf
+*.ps1 text eol=lf
+*.fish text eol=lf
+*.csh text eol=lf
+*.sh text eol=lf
diff --git a/docs/changelog/1818.bugfix.rst b/docs/changelog/1818.bugfix.rst
new file mode 100644
index 0000000..8396cb9
--- /dev/null
+++ b/docs/changelog/1818.bugfix.rst
@@ -0,0 +1 @@
+For activation scripts always use UNIX line endings (unless it's BATCH shell related) - by :user:`saytosid`.
diff --git a/src/virtualenv/activation/powershell/activate.ps1 b/src/virtualenv/activation/powershell/activate.ps1
index 85b2103..a370a63 100644
--- a/src/virtualenv/activation/powershell/activate.ps1
+++ b/src/virtualenv/activation/powershell/activate.ps1
@@ -1,60 +1,60 @@
-$script:THIS_PATH = $myinvocation.mycommand.path
-$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
-
-function global:deactivate([switch] $NonDestructive) {
- if (Test-Path variable:_OLD_VIRTUAL_PATH) {
- $env:PATH = $variable:_OLD_VIRTUAL_PATH
- Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
- }
-
- if (Test-Path function:_old_virtual_prompt) {
- $function:prompt = $function:_old_virtual_prompt
- Remove-Item function:\_old_virtual_prompt
- }
-
- if ($env:VIRTUAL_ENV) {
- Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
- }
-
- if (!$NonDestructive) {
- # Self destruct!
- Remove-Item function:deactivate
- Remove-Item function:pydoc
- }
-}
-
-function global:pydoc {
- python -m pydoc $args
-}
-
-# unset irrelevant variables
-deactivate -nondestructive
-
-$VIRTUAL_ENV = $BASE_DIR
-$env:VIRTUAL_ENV = $VIRTUAL_ENV
-
-New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
-
-$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
-if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
- function global:_old_virtual_prompt {
- ""
- }
- $function:_old_virtual_prompt = $function:prompt
-
- if ("__VIRTUAL_PROMPT__" -ne "") {
- function global:prompt {
- # Add the custom prefix to the existing prompt
- $previous_prompt_value = & $function:_old_virtual_prompt
- ("__VIRTUAL_PROMPT__" + $previous_prompt_value)
- }
- }
- else {
- function global:prompt {
- # Add a prefix to the current prompt, but don't discard it.
- $previous_prompt_value = & $function:_old_virtual_prompt
- $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
- ($new_prompt_value + $previous_prompt_value)
- }
- }
-}
+$script:THIS_PATH = $myinvocation.mycommand.path
+$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
+
+function global:deactivate([switch] $NonDestructive) {
+ if (Test-Path variable:_OLD_VIRTUAL_PATH) {
+ $env:PATH = $variable:_OLD_VIRTUAL_PATH
+ Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
+ }
+
+ if (Test-Path function:_old_virtual_prompt) {
+ $function:prompt = $function:_old_virtual_prompt
+ Remove-Item function:\_old_virtual_prompt
+ }
+
+ if ($env:VIRTUAL_ENV) {
+ Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
+ }
+
+ if (!$NonDestructive) {
+ # Self destruct!
+ Remove-Item function:deactivate
+ Remove-Item function:pydoc
+ }
+}
+
+function global:pydoc {
+ python -m pydoc $args
+}
+
+# unset irrelevant variables
+deactivate -nondestructive
+
+$VIRTUAL_ENV = $BASE_DIR
+$env:VIRTUAL_ENV = $VIRTUAL_ENV
+
+New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
+
+$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
+if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
+ function global:_old_virtual_prompt {
+ ""
+ }
+ $function:_old_virtual_prompt = $function:prompt
+
+ if ("__VIRTUAL_PROMPT__" -ne "") {
+ function global:prompt {
+ # Add the custom prefix to the existing prompt
+ $previous_prompt_value = & $function:_old_virtual_prompt
+ ("__VIRTUAL_PROMPT__" + $previous_prompt_value)
+ }
+ }
+ else {
+ function global:prompt {
+ # Add a prefix to the current prompt, but don't discard it.
+ $previous_prompt_value = & $function:_old_virtual_prompt
+ $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
+ ($new_prompt_value + $previous_prompt_value)
+ }
+ }
+}
diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py
index 7a9d3c8..14f0979 100644
--- a/src/virtualenv/activation/via_template.py
+++ b/src/virtualenv/activation/via_template.py
@@ -11,9 +11,9 @@ from virtualenv.util.six import ensure_text
from .activator import Activator
if sys.version_info >= (3, 7):
- from importlib.resources import read_text
+ from importlib.resources import read_binary
else:
- from importlib_resources import read_text
+ from importlib_resources import read_binary
@add_metaclass(ABCMeta)
@@ -44,7 +44,8 @@ class ViaTemplateActivator(Activator):
for template in templates:
text = self.instantiate_template(replacements, template, creator)
dest = to_folder / self.as_name(template)
- dest.write_text(text, encoding="utf-8")
+ # use write_bytes to avoid platform specific line normalization (\n -> \r\n)
+ dest.write_bytes(text.encode("utf-8"))
generated.append(dest)
return generated
@@ -52,8 +53,9 @@ class ViaTemplateActivator(Activator):
return template.name
def instantiate_template(self, replacements, template, creator):
- # read text and do replacements
- text = read_text(self.__module__, str(template), encoding="utf-8", errors="strict")
+ # read content as binary to avoid platform specific line normalization (\n -> \r\n)
+ binary = read_binary(self.__module__, str(template))
+ text = binary.decode("utf-8", errors="strict")
for key, value in replacements.items():
value = self._repr_unicode(creator, value)
text = text.replace(key, value)
diff --git a/src/virtualenv/create/via_global_ref/api.py b/src/virtualenv/create/via_global_ref/api.py
index c9eab3c..6f296f4 100644
--- a/src/virtualenv/create/via_global_ref/api.py
+++ b/src/virtualenv/create/via_global_ref/api.py
@@ -8,6 +8,7 @@ from six import add_metaclass
from virtualenv.info import fs_supports_symlink
from virtualenv.util.path import Path
+from virtualenv.util.six import ensure_text
from ..creator import Creator, CreatorMeta
@@ -91,10 +92,10 @@ class ViaGlobalRefApi(Creator):
text = self.env_patch_text()
if text:
pth = self.purelib / "_virtualenv.pth"
- logging.debug("create virtualenv import hook file %s", pth)
+ logging.debug("create virtualenv import hook file %s", ensure_text(str(pth)))
pth.write_text("import _virtualenv")
dest_path = self.purelib / "_virtualenv.py"
- logging.debug("create %s", dest_path)
+ logging.debug("create %s", ensure_text(str(dest_path)))
dest_path.write_text(text)
def env_patch_text(self):
diff --git a/src/virtualenv/util/path/_pathlib/via_os_path.py b/src/virtualenv/util/path/_pathlib/via_os_path.py
index d11aeaa..ac78d4f 100644
--- a/src/virtualenv/util/path/_pathlib/via_os_path.py
+++ b/src/virtualenv/util/path/_pathlib/via_os_path.py
@@ -87,9 +87,12 @@ class Path(object):
with open(self._path, "rb") as file_handler:
return file_handler.read()
- def write_text(self, text, encoding="utf-8"):
+ def write_bytes(self, content):
with open(self._path, "wb") as file_handler:
- file_handler.write(text.encode(encoding))
+ file_handler.write(content)
+
+ def write_text(self, text, encoding="utf-8"):
+ self.write_bytes(text.encode(encoding))
def iterdir(self):
for p in os.listdir(self._path):
diff --git a/tests/unit/activation/conftest.py b/tests/unit/activation/conftest.py
index 98c3fda..bb3e292 100644
--- a/tests/unit/activation/conftest.py
+++ b/tests/unit/activation/conftest.py
@@ -31,6 +31,7 @@ class ActivationTester(object):
self.pydoc_call = "pydoc -w pydoc_test"
self.script_encoding = "utf-8"
self._version = None
+ self.unix_line_ending = True
def get_version(self, raise_on_fail):
if self._version is None:
@@ -63,6 +64,16 @@ class ActivationTester(object):
def __call__(self, monkeypatch, tmp_path):
activate_script = self._creator.bin_dir / self.activate_script
+
+ # check line endings are correct type
+ script_content = activate_script.read_bytes()
+ for line in script_content.split(b"\n")[:-1]:
+ cr = b"\r" if sys.version_info.major == 2 else 13
+ if self.unix_line_ending:
+ assert line == b"" or line[-1] != cr, script_content.decode("utf-8")
+ else:
+ assert line[-1] == cr, script_content.decode("utf-8")
+
test_script = self._generate_test_script(activate_script, tmp_path)
monkeypatch.chdir(ensure_text(str(tmp_path)))
diff --git a/tests/unit/activation/test_bash.py b/tests/unit/activation/test_bash.py
index 5246be0..51498ed 100644
--- a/tests/unit/activation/test_bash.py
+++ b/tests/unit/activation/test_bash.py
@@ -1,13 +1,12 @@
from __future__ import absolute_import, unicode_literals
-import sys
-
import pytest
from virtualenv.activation import BashActivator
+from virtualenv.info import IS_WIN
-@pytest.mark.skipif(sys.platform == "win32", reason="Github Actions ships with WSL bash")
+@pytest.mark.skipif(IS_WIN, reason="Github Actions ships with WSL bash")
def test_bash(raise_on_non_source_class, activation_tester):
class Bash(raise_on_non_source_class):
def __init__(self, session):
diff --git a/tests/unit/activation/test_batch.py b/tests/unit/activation/test_batch.py
index 92b141b..e10d902 100644
--- a/tests/unit/activation/test_batch.py
+++ b/tests/unit/activation/test_batch.py
@@ -17,6 +17,7 @@ def test_batch(activation_tester_class, activation_tester, tmp_path, activation_
self.deactivate = "call deactivate"
self.activate_cmd = "call"
self.pydoc_call = "call {}".format(self.pydoc_call)
+ self.unix_line_ending = False
def _get_test_lines(self, activate_script):
# for BATCH utf-8 support need change the character code page to 650001
diff --git a/tests/unit/activation/test_python_activator.py b/tests/unit/activation/test_python_activator.py
index 6abf255..859fad6 100644
--- a/tests/unit/activation/test_python_activator.py
+++ b/tests/unit/activation/test_python_activator.py
@@ -6,7 +6,7 @@ from ast import literal_eval
from textwrap import dedent
from virtualenv.activation import PythonActivator
-from virtualenv.info import WIN_CPYTHON_2
+from virtualenv.info import IS_WIN, WIN_CPYTHON_2
from virtualenv.util.six import ensure_text
@@ -21,6 +21,7 @@ def test_python(raise_on_non_source_class, activation_tester):
extension="py",
non_source_fail_message="You must use exec(open(this_file).read(), {'__file__': this_file}))",
)
+ self.unix_line_ending = not IS_WIN
def env(self, tmp_path):
env = os.environ.copy()