Repository: conan-io/conan

Issue:
Enhanced tools.vcvars_dict(...,only_diff=True) handling of lists
To help us debug your issue please explain:

- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

Conan 1.5.1, Windows 7, Visual Studio 2017

tools.vcvars_dict seems to mostly exist to support `with tools.vcvars():`. However, this doesn't play nicely with any other packages offering additions to the the same environment variables (filter_known_paths offers a partial workaround for PATH),

environment_append and env_info handle this use case nicely by supporting the idea that the dict value an be a list, and that this will be combined with the existing values using os.pathsep. So it would be nice if tools.vcvars_dict would, in only_diff=True, make use of this and split lists that vcvars modified by inserting additional entries at the front, rather than providing a blanket "overwrite with this complete string".

e.g. 

https://github.com/conan-io/conan/blob/a8649076fa6bfeb6c0b7438832fd996e56d72ecf/conans/client/tools/win.py#L322-L323

could instead do something like (not tested)

```python
    oldvalue = os.environ.get(name_var) if only_diff else None 

    if oldvalue and value.endswith(os.pathsep + oldvalue):
        new_env[name_var] = value[:-(len(oldvalue)+1)].split(os.pathsep)
    elif oldvalue != value:
        new_env[name_var] = value
```





Discussion:
Interesting. We will have a look.

Resolving patch:
diff --git a/conans/client/tools/win.py b/conans/client/tools/win.py
--- a/conans/client/tools/win.py
+++ b/conans/client/tools/win.py
@@ -303,7 +303,7 @@ def vcvars_command(settings, arch=None, compiler_version=None, force=False, vcva
 
 def vcvars_dict(settings, arch=None, compiler_version=None, force=False, filter_known_paths=False,
                 vcvars_ver=None, winsdk_version=None, only_diff=True):
-
+    known_path_lists = ("INCLUDE", "LIB", "LIBPATH", "PATH")
     cmd = vcvars_command(settings, arch=arch,
                          compiler_version=compiler_version, force=force,
                          vcvars_ver=vcvars_ver, winsdk_version=winsdk_version) + " && echo __BEGINS__ && set"
@@ -321,8 +321,22 @@ def vcvars_dict(settings, arch=None, compiler_version=None, force=False, filter_
             continue
         try:
             name_var, value = line.split("=", 1)
-            if not only_diff or os.environ.get(name_var) != value:
-                new_env[name_var] = value
+            new_value = value.split(os.pathsep) if name_var in known_path_lists else value
+            # Return only new vars & changed ones, but only with the changed elements if the var is
+            # a list
+            if only_diff:
+                old_value = os.environ.get(name_var)
+                # The new value ends with separator and the old value, is a list, get only the
+                # new elements
+                if old_value and value.endswith(os.pathsep + old_value):
+                    new_env[name_var] = value[:-(len(old_value) + 1)].split(os.pathsep)
+                elif value != old_value:
+                    # Only if the vcvars changed something, we return the variable,
+                    # otherwise is not vcvars related
+                    new_env[name_var] = new_value
+            else:
+                new_env[name_var] = new_value
+
         except ValueError:
             pass
 


Test patch:
diff --git a/conans/test/util/tools_test.py b/conans/test/util/tools_test.py
--- a/conans/test/util/tools_test.py
+++ b/conans/test/util/tools_test.py
@@ -759,6 +759,20 @@ def vcvars_dict_diff_test(self):
             self.assertNotIn("MYVAR", ret)
             self.assertIn("VCINSTALLDIR", ret)
 
+        my_lib_paths = "C:\\PATH\TO\MYLIBS;C:\\OTHER_LIBPATH"
+        with tools.environment_append({"LIBPATH": my_lib_paths}):
+            ret = vcvars_dict(settings, only_diff=False)
+            str_var_value = os.pathsep.join(ret["LIBPATH"])
+            self.assertTrue(str_var_value.endswith(my_lib_paths))
+
+            # Now only a diff, it should return the values as a list, but without the old values
+            ret = vcvars_dict(settings, only_diff=True)
+            self.assertEquals(ret["LIBPATH"], str_var_value.split(os.pathsep)[0:-2])
+
+            # But if we apply both environments, they are composed correctly
+            with tools.environment_append(ret):
+                self.assertEquals(os.environ["LIBPATH"], str_var_value)
+
     def vcvars_dict_test(self):
         # https://github.com/conan-io/conan/issues/2904
         output_with_newline_and_spaces = """__BEGINS__