Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New revision_mode = scm_folder for monorepos #13562

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions conans/client/cmd/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def cmd_export(app, conanfile_path, name, version, user, channel, graph_lock=Non


def _calc_revision(scoped_output, path, manifest, revision_mode):
if revision_mode not in ["scm", "hash"]:
if revision_mode not in ["scm", "scm_folder", "hash"]:
raise ConanException("Revision mode should be one of 'hash' (default) or 'scm'")

# Use the proper approach depending on 'revision_mode'
Expand All @@ -93,7 +93,8 @@ def _calc_revision(scoped_output, path, manifest, revision_mode):
else:
try:
with chdir(path):
rev_detected = check_output_runner('git rev-list HEAD -n 1 --full-history').strip()
f = '-- "."' if revision_mode == "scm_folder" else ""
revision = check_output_runner(f'git rev-list HEAD -n 1 --full-history {f}').strip()
except Exception as exc:
error_msg = "Cannot detect revision using '{}' mode from repository at " \
"'{}'".format(revision_mode, path)
Expand All @@ -104,8 +105,6 @@ def _calc_revision(scoped_output, path, manifest, revision_mode):
raise ConanException("Can't have a dirty repository using revision_mode='scm' and doing"
" 'conan export', please commit the changes and run again.")

revision = rev_detected

scoped_output.info("Using git commit as the recipe revision: %s" % revision)

return revision
Expand Down
66 changes: 51 additions & 15 deletions conans/test/functional/command/export_test.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,66 @@
import textwrap
import unittest
import os

import pytest

from conans.model.recipe_ref import RecipeReference
from conans.test.assets.genconanfile import GenConanfile
from conans.test.utils.scm import git_add_changes_commit
from conans.test.utils.tools import TestClient


class ExportMetadataTest(unittest.TestCase):
conanfile = textwrap.dedent("""
from conan import ConanFile
@pytest.mark.tool("git")
class TestRevisionModeSCM:

class Lib(ConanFile):
revision_mode = "{revision_mode}"
""")
def test_revision_mode_scm(self):
t = TestClient()
conanfile = str(GenConanfile().with_class_attribute('revision_mode = "scm"'))
commit = t.init_git_repo({'conanfile.py': conanfile})

summary_hash = "bfe8b4a6a2a74966c0c4e0b34705004a"
t.run(f"export . --name=pkg --version=0.1")

@pytest.mark.tool("git")
def test_revision_mode_scm(self):
ref = RecipeReference.loads("pkg/0.1")
latest_rev = t.cache.get_latest_recipe_reference(ref)
assert latest_rev.revision == commit

# Now it will fail if dirty
t.save({"conanfile.py": conanfile + "\n#comment"})
t.run(f"export . --name=pkg --version=0.1", assert_error=True)
assert "Can't have a dirty repository using revision_mode='scm' and doing" in t.out
# Commit to fix
commit2 = git_add_changes_commit(t.current_folder, msg="fix")
t.run(f"export . --name=pkg --version=0.1")
latest_rev = t.cache.get_latest_recipe_reference(ref)
assert latest_rev.revision == commit2

def test_revision_mode_scm_subfolder(self):
""" emulates a mono-repo with 2 subprojects, when a change is done in a subproject
it gets a different folder commit
"""
t = TestClient()
commit = t.init_git_repo({'conanfile.py': self.conanfile.format(revision_mode="scm")})
conanfile = str(GenConanfile().with_class_attribute('revision_mode = "scm_folder"'))
commit = t.init_git_repo({'pkga/conanfile.py': conanfile,
'pkgb/conanfile.py': conanfile})

ref = RecipeReference.loads("name/version@user/channel")
t.run(f"export . --name={ref.name} --version={ref.version} --user={ref.user} --channel={ref.channel}")
t.save({"pkgb/conanfile.py": conanfile + "\n#comment"})
commit_b = git_add_changes_commit(os.path.join(t.current_folder, "pkgb"), msg="fix")

# pkga still gets the initial commit, as it didn't change its contents
t.run(f"export pkga --name=pkga --version=0.1")
ref = RecipeReference.loads("pkga/0.1")
latest_rev = t.cache.get_latest_recipe_reference(ref)
assert latest_rev.revision == commit

self.assertEqual(latest_rev.revision, commit)
# but pkgb will get the commit of the new changed folder
t.run(f"export pkgb --name=pkgb --version=0.1")
ref = RecipeReference.loads("pkgb/0.1")
latest_rev = t.cache.get_latest_recipe_reference(ref)
assert latest_rev.revision == commit_b

def test_auto_revision_without_commits(self):
"""If we have a repo but without commits, it has to fail when the revision_mode=scm"""
t = TestClient()
t.run_command('git init .')
t.save({"conanfile.py": GenConanfile("lib", "0.1").with_revision_mode("scm")})
t.run("export .", assert_error=True)
# It errors, because no commits yet
assert "Cannot detect revision using 'scm' mode from repository" in t.out
29 changes: 0 additions & 29 deletions conans/test/functional/revisions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,35 +796,6 @@ def test_upload_no_overwrite_packages(self):
pref2.revision)


class SCMRevisions(unittest.TestCase):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests were redundant, consolidated them in the above tests


def test_auto_revision_even_without_scm_git(self):
"""
Can't do conan create/export with uncommited changes if using revision_mode=scm
"""
ref = RecipeReference.loads("lib/1.0@conan/testing")
client = TurboTestClient()
conanfile = GenConanfile().with_revision_mode("scm")
commit = client.init_git_repo(files={"file.txt": "hey", "conanfile.py": str(conanfile)},
origin_url="http://myrepo.git")
client.create(ref, conanfile=conanfile)
self.assertEqual(client.recipe_revision(ref), commit)

# Change the conanfile and make another create, the revision should be the same
client.save({"conanfile.py": str(conanfile.with_build_msg("New changes!"))})
client.create(ref, conanfile=conanfile, assert_error=True)
self.assertIn("Can't have a dirty repository using revision_mode='scm' and doing", client.out)

def test_auto_revision_without_commits(self):
"""If we have a repo but without commits, it has to fail when the revision_mode=scm"""
client = TurboTestClient()
client.run_command('git init .')
client.save({"conanfile.py": GenConanfile("lib", "0.1").with_revision_mode("scm")})
client.run("create .", assert_error=True)
# It error, because the revision_mode is explicitly set to scm
self.assertIn("Cannot detect revision using 'scm' mode from repository", client.out)


class CapabilitiesRevisionsTest(unittest.TestCase):
def test_server_with_only_v2_capability(self):
server = TestServer(server_capabilities=[])
Expand Down