Skip to content

Commit

Permalink
fix relativize paths in Environment generated files (#15592)
Browse files Browse the repository at this point in the history
* fix relativize paths in generated files

* Fix msvc profile detect test (#15552)

remove test line

Co-authored-by: Rubén Rincón Blanco <rubenrb@jfrog.com>

* recover xfail test for win_bash=True with msvc (#15593)

* Not skipping binaries of direct dependencies for packages being built (#15128)

* to explorer teh concept of not skipping directs

* fix

* wip

* review

* wip

---------

Co-authored-by: Juan <35701596+juansblanco@users.noreply.github.com>
Co-authored-by: Rubén Rincón Blanco <rubenrb@jfrog.com>
  • Loading branch information
3 people authored Feb 12, 2024
1 parent 8396863 commit cd05d59
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 14 deletions.
32 changes: 22 additions & 10 deletions conan/tools/env/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from collections import OrderedDict
from contextlib import contextmanager

from conans.client.generators import relativize_generated_file
from conans.client.generators import relativize_paths
from conans.client.subsystems import deduce_subsystem, WINDOWS, subsystem_path
from conan.errors import ConanException
from conans.model.recipe_ref import ref_matches
Expand Down Expand Up @@ -135,12 +135,14 @@ def compose_env_value(self, other):
new_value[index:index + 1] = other._values # replace the placeholder
self._values = new_value

def get_str(self, placeholder, subsystem, pathsep):
def get_str(self, placeholder, subsystem, pathsep, root_path=None, script_path=None):
"""
:param subsystem:
:param placeholder: a OS dependant string pattern of the previous env-var value like
$PATH, %PATH%, et
:param pathsep: The path separator, typically ; or :
:param root_path: To do a relativize of paths, the base root path to be replaced
:param script_path: the replacement instead of the script path
:return: a string representation of the env-var value, including the $NAME-like placeholder
"""
values = []
Expand All @@ -151,6 +153,13 @@ def get_str(self, placeholder, subsystem, pathsep):
else:
if self._path:
v = subsystem_path(subsystem, v)
if root_path is not None:
if v.startswith(root_path): # relativize
v = v.replace(root_path, script_path, 1)
elif os.sep == "\\": # Just in case user specified C:/path/to/somewhere
r = root_path.replace("\\", "/")
if v.startswith(r):
v = v.replace(r, script_path.replace("\\", "/"))
values.append(v)
if self._path:
return pathsep.join(values)
Expand Down Expand Up @@ -329,7 +338,7 @@ class EnvVars:
"""
def __init__(self, conanfile, values, scope):
self._values = values # {var_name: _EnvValue}, just a reference to the Environment
self._values = values # {var_name: _EnvValue}, just a reference to the Environment
self._conanfile = conanfile
self._scope = scope
self._subsystem = deduce_subsystem(conanfile, scope)
Expand Down Expand Up @@ -418,12 +427,13 @@ def save_bat(self, file_location, generate_deactivate=True):
{deactivate}
""").format(deactivate=deactivate if generate_deactivate else "")
result = [capture]
abs_base_path, new_path = relativize_paths(self._conanfile, "%~dp0")
for varname, varvalues in self._values.items():
value = varvalues.get_str("%{name}%", subsystem=self._subsystem, pathsep=self._pathsep)
value = varvalues.get_str("%{name}%", subsystem=self._subsystem, pathsep=self._pathsep,
root_path=abs_base_path, script_path=new_path)
result.append('set "{}={}"'.format(varname, value))

content = "\n".join(result)
content = relativize_generated_file(content, self._conanfile, "%~dp0")
# It is very important to save it correctly with utf-8, the Conan util save() is broken
os.makedirs(os.path.dirname(os.path.abspath(file_location)), exist_ok=True)
open(file_location, "w", encoding="utf-8").write(content)
Expand Down Expand Up @@ -459,24 +469,25 @@ def save_ps1(self, file_location, generate_deactivate=True,):
{deactivate}
""").format(deactivate=deactivate if generate_deactivate else "")
result = [capture]
abs_base_path, new_path = relativize_paths(self._conanfile, "$PSScriptRoot")
for varname, varvalues in self._values.items():
value = varvalues.get_str("$env:{name}", subsystem=self._subsystem, pathsep=self._pathsep)
value = varvalues.get_str("$env:{name}", subsystem=self._subsystem, pathsep=self._pathsep,
root_path=abs_base_path, script_path=new_path)
if value:
value = value.replace('"', '`"') # escape quotes
result.append('$env:{}="{}"'.format(varname, value))
else:
result.append('if (Test-Path env:{0}) {{ Remove-Item env:{0} }}'.format(varname))

content = "\n".join(result)
content = relativize_generated_file(content, self._conanfile, "$PSScriptRoot")
# It is very important to save it correctly with utf-16, the Conan util save() is broken
# and powershell uses utf-16 files!!!
os.makedirs(os.path.dirname(os.path.abspath(file_location)), exist_ok=True)
open(file_location, "w", encoding="utf-16").write(content)

def save_sh(self, file_location, generate_deactivate=True):
filepath, filename = os.path.split(file_location)
deactivate_file = os.path.join(filepath, "deactivate_{}".format(filename))
deactivate_file = os.path.join("$script_folder", "deactivate_{}".format(filename))
deactivate = textwrap.dedent("""\
echo "echo Restoring environment" > "{deactivate_file}"
for v in {vars}
Expand All @@ -495,16 +506,17 @@ def save_sh(self, file_location, generate_deactivate=True):
{deactivate}
""").format(deactivate=deactivate if generate_deactivate else "")
result = [capture]
abs_base_path, new_path = relativize_paths(self._conanfile, "$script_folder")
for varname, varvalues in self._values.items():
value = varvalues.get_str("${name}", self._subsystem, pathsep=self._pathsep)
value = varvalues.get_str("${name}", self._subsystem, pathsep=self._pathsep,
root_path=abs_base_path, script_path=new_path)
value = value.replace('"', '\\"')
if value:
result.append('export {}="{}"'.format(varname, value))
else:
result.append('unset {}'.format(varname))

content = "\n".join(result)
content = relativize_generated_file(content, self._conanfile, "$script_folder")
content = f'script_folder="{os.path.abspath(filepath)}"\n' + content
save(file_location, content)

Expand Down
15 changes: 11 additions & 4 deletions conans/client/generators/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,21 @@ def ps1_content(files):


def relativize_generated_file(content, conanfile, placeholder):
abs_base_path, new_path = relativize_paths(conanfile, placeholder)
if abs_base_path is None:
return content
content = content.replace(abs_base_path, new_path)
content = content.replace(abs_base_path.replace("\\", "/"), new_path.replace("\\", "/"))
return content


def relativize_paths(conanfile, placeholder):
abs_base_path = conanfile.folders._base_generators
if not abs_base_path or not os.path.isabs(abs_base_path):
return content
return None, None
abs_base_path = os.path.join(abs_base_path, "") # For the trailing / to dissambiguate matches
generators_folder = conanfile.generators_folder
rel_path = os.path.relpath(abs_base_path, generators_folder)
new_path = placeholder if rel_path == "." else os.path.join(placeholder, rel_path)
new_path = os.path.join(new_path, "") # For the trailing / to dissambiguate matches
content = content.replace(abs_base_path, new_path)
content = content.replace(abs_base_path.replace("\\", "/"), new_path.replace("\\", "/"))
return content
return abs_base_path, new_path
11 changes: 11 additions & 0 deletions conans/test/integration/environment/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,3 +841,14 @@ def test(self):
c.run("create tool --build-require -s:b build_type=Release -s:h build_type=Debug")
assert "tool/0.1 (test package): Building TEST_PACKAGE IN Debug!!" in c.out
assert "MYLIBVAR=MYLIBVALUE:Release" in c.out


def test_deactivate_relocatable_substitute():
c = TestClient()
# this cannot be tested in CI, because permissions over root folder
# c.current_folder = "/build"
c.save({"conanfile.py": GenConanfile("pkg", "0.1")})
c.run("install . -s os=Linux -s:b os=Linux")
conanbuild = c.load("conanbuildenv.sh")
result = os.path.join("$script_folder", "deactivate_conanbuildenv.sh")
assert f'"{result}"' in conanbuild

0 comments on commit cd05d59

Please sign in to comment.