Repository: conan-io/conan

Issue:
Revisions: Manage non-pristine state in repo to capture the revision
What to do during the export if the SCM folder contains not committed changes?
Mark in metadata as "dirty" and forbid upload?
What if we enable `scm_mode` to `hash` but still using `scm` feature? #4413
What if we don't use `scm` feature but revisions?  Looks like it has to be marked as `dirty` both if we use the `scm_mode` as revisions mode and/or if we use the `scm` feature.


Discussion:
For the moment, just print a warning if the repo is not pristine when capturing there the revision.
We are not sure if, for example, in CI, they build in the repository and there are no excluded files, so it can block. The ci builds are usually pretty dirty.

Resolving patch:
diff --git a/conans/client/cmd/export.py b/conans/client/cmd/export.py
--- a/conans/client/cmd/export.py
+++ b/conans/client/cmd/export.py
@@ -229,24 +229,26 @@ def _replace_scm_data_in_conanfile(conanfile_path, scm_data):
 
 def _detect_scm_revision(path):
     if not path:
-        return None, None
+        return None, None, None
 
     repo_type = SCM.detect_scm(path)
     if not repo_type:
-        return None, None
+        return None, None, None
 
     repo_obj = SCM.availables.get(repo_type)(path)
-    return repo_obj.get_revision(), repo_type
+    return repo_obj.get_revision(), repo_type, repo_obj.is_pristine()
 
 
 def _update_revision_in_metadata(package_layout, revisions_enabled, output, path, digest):
 
-    scm_revision_detected, repo_type = _detect_scm_revision(path)
+    scm_revision_detected, repo_type, is_pristine = _detect_scm_revision(path)
     revision = scm_revision_detected or digest.summary_hash
     if revisions_enabled:
         if scm_revision_detected:
             output.info("Using {} commit as the recipe"
                         " revision: {} ".format(repo_type, revision))
+            if not is_pristine:
+                output.warn("Repo status is not pristine: there might be modified files")
         else:
             output.info("Using the exported files summary hash as the recipe"
                         " revision: {} ".format(revision))


Test patch:
diff --git a/conans/test/unittests/client/cmd/export/test_update_revision_in_metadata.py b/conans/test/unittests/client/cmd/export/test_update_revision_in_metadata.py
new file mode 100644
--- /dev/null
+++ b/conans/test/unittests/client/cmd/export/test_update_revision_in_metadata.py
@@ -0,0 +1,27 @@
+# coding=utf-8
+
+
+import unittest
+
+from mock import mock
+
+from conans.client.cmd.export import _update_revision_in_metadata
+from conans.model.ref import ConanFileReference
+from conans.paths.package_layouts.package_cache_layout import PackageCacheLayout
+from conans.test.utils.test_files import temp_folder
+from conans.test.utils.tools import TestBufferConanOutput
+
+
+class UpdateRevisionInMetadataTests(unittest.TestCase):
+
+    def test_warn_not_pristine(self):
+        output = TestBufferConanOutput()
+
+        with mock.patch("conans.client.cmd.export._detect_scm_revision",
+                        return_value=("revision", "git", False)):
+            path = digest = None
+            ref = ConanFileReference.loads("lib/version@user/channel")
+            package_layout = PackageCacheLayout(base_folder=temp_folder(), ref=ref,
+                                                short_paths=False, no_lock=True)
+            _update_revision_in_metadata(package_layout, True, output, path, digest)
+            self.assertIn("WARN: Repo status is not pristine: there might be modified files", output)