From 6a394311421f78054c6eeeb4f77ddb0d7eb263c8 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 16 Feb 2023 10:41:08 +0100 Subject: [PATCH] Git.fetch_commit (#13096) * Git.fetch_commit * skip in linux * fix --- conan/tools/scm/git.py | 13 ++++++ conans/test/functional/tools/scm/test_git.py | 47 ++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/conan/tools/scm/git.py b/conan/tools/scm/git.py index 1032d5b6924..e6fe909a71c 100644 --- a/conan/tools/scm/git.py +++ b/conan/tools/scm/git.py @@ -84,6 +84,19 @@ def clone(self, url, target="", args=None): self._conanfile.output.info("Cloning git repo") self.run('clone "{}" {} {}'.format(url, " ".join(args), target)) + def fetch_commit(self, url, commit): + """ + Experimental: does a 1 commit fetch and checkout, instead of a full clone, + should be faster. + """ + if os.path.exists(url): + url = url.replace("\\", "/") # Windows local directory + self._conanfile.output.info("Shallow fetch of git repo") + self.run('init') + self.run(f'remote add origin "{url}"') + self.run(f'fetch --depth 1 origin {commit}') + self.run(f'checkout FETCH_HEAD') + def checkout(self, commit): self._conanfile.output.info("Checkout: {}".format(commit)) self.run('checkout {}'.format(commit)) diff --git a/conans/test/functional/tools/scm/test_git.py b/conans/test/functional/tools/scm/test_git.py index 4993195415c..0b3d822a33f 100644 --- a/conans/test/functional/tools/scm/test_git.py +++ b/conans/test/functional/tools/scm/test_git.py @@ -1,4 +1,5 @@ import os +import platform import re import textwrap @@ -209,6 +210,52 @@ def test_clone_checkout(self): assert c.load("source/CMakeLists.txt") == "mycmake" +class TestGitShallowClone: + """ base Git cloning operations + """ + conanfile = textwrap.dedent(""" + import os + from conan import ConanFile + from conan.tools.scm import Git + from conan.tools.files import load + + class Pkg(ConanFile): + name = "pkg" + version = "0.1" + + def layout(self): + self.folders.source = "source" + + def source(self): + git = Git(self) + git.fetch_commit(url="{url}", commit="{commit}") + self.output.info("MYCMAKE: {{}}".format(load(self, "CMakeLists.txt"))) + self.output.info("MYFILE: {{}}".format(load(self, "src/myfile.h"))) + """) + + @pytest.mark.skipif(platform.system() == "Linux", reason="Git version in Linux not support it") + def test_clone_checkout(self): + folder = os.path.join(temp_folder(), "myrepo") + url, commit = create_local_git_repo(files={"src/myfile.h": "myheader!", + "CMakeLists.txt": "mycmake"}, folder=folder) + # This second commit will NOT be used, as I will use the above commit in the conanfile + save_files(path=folder, files={"src/myfile.h": "my2header2!"}) + git_add_changes_commit(folder=folder) + + c = TestClient() + c.save({"conanfile.py": self.conanfile.format(url=url, commit=commit)}) + c.run("create .") + assert "pkg/0.1: MYCMAKE: mycmake" in c.out + assert "pkg/0.1: MYFILE: myheader!" in c.out + + # It also works in local flow + c.run("source .") + assert "conanfile.py (pkg/0.1): MYCMAKE: mycmake" in c.out + assert "conanfile.py (pkg/0.1): MYFILE: myheader!" in c.out + assert c.load("source/src/myfile.h") == "myheader!" + assert c.load("source/CMakeLists.txt") == "mycmake" + + class TestGitCloneWithArgs: """ Git cloning passing additional arguments """