Repository: conan-io/conan

Issue:
[feature] Ability to run `conan profile detect` w/o error and w/o overwriting when the profile already exists
### What is your suggestion?

I am using `conan` as a part of a source-level distribution system on `npm` for JavaScript packages that contain C++ code (compiled to native binary for Node.js and to WASM for the browser). `conan` enables me to produce self-contained builds without having to maintain all the included libraries.

Currently, all my build scripts start with:

```
{{platform.python}} -m pip install --user git+https://github.com/conan-io/conan # because of #15867
{{platform.python}} -m conans.conan profile detect || echo ok
{{platform.python}} -m conans.conan install ..... <very long line>
```

The second line works with both `bash` and `cmd.exe` but it would be even better if there was a `--if-not-exists` option - so that all my builds do not start with an error. I could of course create a special profile and overwrite it at each invocation - or even create my own `conan` home directory, but I think that I should support the case where the user has an already existing `conan` profile that contains custom options.

### Have you read the CONTRIBUTING guide?

- [X] I've read the CONTRIBUTING guide


Discussion:
Hi @mmomtchev 

Some quick feedback first: the usage of ``conans.conan`` is not documented, not part of the public interface. This is guaranteed to change in some future Conan release, when we will refactor the code internals.

For not raising an error for ``conan profile detect``, there is already the ``--force`` flag. But that would indeed overwrite the existing ``default`` profile.

I think what is incompatible is both having a modified ``default`` profile and also calling ``conan profile detect`` to detect the ``default`` profile. The not overwrite error is there for this reason, to protect against this.

The strategy should probably be different:
- Manage your own profiles explicitly, name them and use them explicitly. Manage them with ``conan config install``
- Detect and use a different name than the profile, like ``conan profile detect --name=myprofile``. The default profile name can also be changed in ``global.conf`` if you want to avoid passing ``-pr=myprofile`` in every invocation.
- You can check yourself in your pipeline with ``conan profile list`` if the ``default`` profile already exist
If I decide to always overwrite, I won't be compatible with an existing `conan` installation - which is could be a good decision. On other hand, parsing the `conan profile list` output in a platform-independent way would require a Node.js or Python script. And alas, a `pip` bin directory - especially the user one - that is not in the `PATH` is a very common occurrence - maybe not on Linux - but quite probable on macOS and Windows. I am afraid that there are no simple alternatives.



Patch:
diff --git a/conan/cli/commands/profile.py b/conan/cli/commands/profile.py
index 27abff00d1f..c188d9c002d 100644
--- a/conan/cli/commands/profile.py
+++ b/conan/cli/commands/profile.py
@@ -58,12 +58,18 @@ def profile_detect(conan_api, parser, subparser, *args):
     """
     subparser.add_argument("--name", help="Profile name, 'default' if not specified")
     subparser.add_argument("-f", "--force", action='store_true', help="Overwrite if exists")
+    subparser.add_argument("-e", "--exist-ok", action='store_true',
+                           help="If the profile already exist, do not detect a new one")
     args = parser.parse_args(*args)
 
     profile_name = args.name or "default"
     profile_pathname = conan_api.profiles.get_path(profile_name, os.getcwd(), exists=False)
-    if not args.force and os.path.exists(profile_pathname):
-        raise ConanException(f"Profile '{profile_pathname}' already exists")
+    if os.path.exists(profile_pathname):
+        if args.exist_ok:
+            ConanOutput().info(f"Profile '{profile_name}' already exists, skipping detection")
+            return
+        if not args.force:
+            raise ConanException(f"Profile '{profile_pathname}' already exists")
 
     detected_profile = conan_api.profiles.detect()
     ConanOutput().success("\nDetected profile:")


Test patch:
diff --git a/conans/test/functional/command/profile_test.py b/conans/test/functional/command/profile_test.py
index acbe89c37a3..e878860ce19 100644
--- a/conans/test/functional/command/profile_test.py
+++ b/conans/test/functional/command/profile_test.py
@@ -128,7 +128,12 @@ def test_profile_new(self):
         assert "MyProfile2' already exists" in c.out
 
         c.run("profile detect --name=./MyProfile2 --force")  # will not raise error
-    
+        assert "build_type=Release" in c.load("MyProfile2")
+        c.save({"MyProfile2": "potato"})
+        c.run("profile detect --name=./MyProfile2 --exist-ok")  # wont raise, won't overwrite
+        assert "Profile './MyProfile2' already exists, skipping detection" in c.out
+        assert c.load("MyProfile2") == "potato"
+
     @pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows and msvc")
     def test_profile_new_msvc_vcvars(self):
         c = TestClient()
@@ -140,8 +145,8 @@ def test_profile_new_msvc_vcvars(self):
         cl_executable = c.out.splitlines()[-1]
         assert os.path.isfile(cl_executable)
         cl_location = os.path.dirname(cl_executable)
-        
-        # Try different variations, including full path and full path with quotes 
+
+        # Try different variations, including full path and full path with quotes
         for var in ["cl", "cl.exe", cl_executable, f'"{cl_executable}"']:
             output = RedirectedTestOutput()
             with redirect_output(output):