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

introducing modern conan.tool.scm.Git helper #10594

Merged
merged 41 commits into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ae66be8
introducing modern conan.tool.scm.Git helper
memsharded Feb 16, 2022
1bfa516
skip Py2, change git config order
memsharded Feb 16, 2022
d811e17
wip
memsharded Feb 16, 2022
ccca294
wip
memsharded Feb 16, 2022
04e356d
Merge branch 'develop' into feature/new_scm_git
memsharded Feb 17, 2022
9c0e46b
wip
memsharded Feb 18, 2022
6af4427
wip
memsharded Feb 20, 2022
eeb123b
let conandata_update create conandata.yml if not exist
memsharded Feb 20, 2022
db807ec
Merge branch 'fix/conandata_update_create' into feature/new_scm_git
memsharded Feb 20, 2022
d77c1a6
full SCM test
memsharded Feb 20, 2022
679ec4b
adding monorepo case
memsharded Feb 21, 2022
683700a
fix test
memsharded Feb 21, 2022
9d3e456
fix test
memsharded Feb 21, 2022
4a63607
Merge branch 'develop' into feature/new_scm_git
memsharded Feb 22, 2022
da035a3
fix tests
memsharded Feb 22, 2022
ea8bd95
fix test
memsharded Feb 22, 2022
42a7a00
merge develop
memsharded Feb 22, 2022
e6ba52a
add subfolder test
memsharded Feb 23, 2022
a4aa3a9
Merge branch 'develop' into feature/new_scm_git
memsharded Feb 23, 2022
a092439
proposing base_source_folder, and folders.root
memsharded Feb 24, 2022
658e7c3
Merge branch 'develop' into feature/base_source_folder
memsharded Feb 24, 2022
29fb041
Merge branch 'develop' into feature/new_scm_git
memsharded Feb 24, 2022
ff7e5e5
Update conans/model/layout.py
memsharded Feb 25, 2022
b01610d
[feature] `ConfDefinition` and `Conf` enhancements. (#10537)
franramirez688 Feb 24, 2022
b5cd928
[PkgConfigDeps] Added new property `component_version` (#10633)
franramirez688 Feb 24, 2022
6209836
package_folder available when "conan install" consumer (#10655)
lasote Feb 24, 2022
13e2a71
added a few conf checkers (#10656)
memsharded Feb 25, 2022
ad8af04
Use absolute paths in conanbuild.sh (#10653)
czoido Feb 25, 2022
3543fcc
Cleanup tmpdirs (#10663)
lasote Feb 25, 2022
64d5c1d
refactor toolchain (#10665)
lasote Feb 28, 2022
604ba15
fix not finding the Premake executable (#10250)
Enhex Feb 28, 2022
b6971ba
review
memsharded Feb 28, 2022
827b39a
Merge branch 'develop' into feature/base_source_folder
memsharded Feb 28, 2022
c6e4317
Merge branch 'develop' into feature/new_scm_git
memsharded Feb 28, 2022
0aba37a
wip
memsharded Feb 28, 2022
45741ba
Merge branch 'feature/base_source_folder' into feature/new_scm_git
memsharded Feb 28, 2022
2cf53db
simplified tests
memsharded Feb 28, 2022
b710317
Merge branch 'develop' into feature/new_scm_git
memsharded Mar 1, 2022
cadb399
new branch test
memsharded Mar 1, 2022
6dde3ca
review
memsharded Mar 2, 2022
18491a6
fix test
memsharded Mar 2, 2022
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
19 changes: 19 additions & 0 deletions conan/tools/files/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hashlib
import os
import platform
import shutil
import subprocess
import sys
from contextlib import contextmanager
Expand All @@ -14,6 +15,7 @@
from conan.tools import CONAN_TOOLCHAIN_ARGS_FILE, CONAN_TOOLCHAIN_ARGS_SECTION
from conans.client.downloaders.download import run_downloader
from conans.errors import ConanException
from conans.util.files import rmdir

if six.PY3: # Remove this IF in develop2
from shutil import which
Expand Down Expand Up @@ -491,3 +493,20 @@ def collect_libs(conanfile, folder=None):
result.append(name)
result.sort()
return result


def swap_child_folder(parent_folder, child_folder):
Copy link
Member Author

Choose a reason for hiding this comment

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

Name to be improved. Suggestions welcome.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe a generic move_folder_contents(dst_folder, folder, clean_first=True) ?

Copy link
Contributor

@czoido czoido Mar 2, 2022

Choose a reason for hiding this comment

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

I think maybe we can split the operation in two, one for removing all folders but the one we want and other for moving the folder... or move_folder_contents(dst_folder, folder, clean_first=True) is more explicit, I'm ok with that too, maybe clean_other instead of clean_first?

Copy link
Member Author

Choose a reason for hiding this comment

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

I am annotating it to NOT document, so we can think about file methods in a more broad perspective, this PR is focused on the Git integration for sources, this is a very minor detail, just to prove it is possible to implement the mono-repo approach

""" replaces the current folder contents with the contents of one child folder. This
is used in the SCM monorepo flow, when it is necessary to use one subproject subfolder
to replace the whole cloned git repo
"""
for f in os.listdir(parent_folder):
if f != child_folder:
path = os.path.join(parent_folder, f)
if os.path.isfile(path):
os.remove(path)
else:
rmdir(path)
child = os.path.join(parent_folder, child_folder)
for f in os.listdir(child):
shutil.move(os.path.join(child, f), os.path.join(parent_folder, f))
1 change: 1 addition & 0 deletions conan/tools/scm/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from conan.tools.scm.git import Git
85 changes: 85 additions & 0 deletions conan/tools/scm/git.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import os

from conan.tools.files import chdir
from conans.errors import ConanException
from conans.util.files import mkdir
from conans.util.runners import check_output_runner


class Git(object):
def __init__(self, conanfile, folder="."):
self._conanfile = conanfile
self.folder = folder

def _run(self, cmd):
with chdir(self._conanfile, self.folder):
return check_output_runner("git {}".format(cmd)).strip()

def get_commit(self):
try:
# commit = self._run("rev-parse HEAD") For the whole repo
# This rev-list knows to capture the last commit for the folder
commit = self._run('rev-list HEAD -n 1 -- "{}"'.format(self.folder))
return commit
except Exception as e:
raise ConanException("Unable to get git commit in '%s': %s" % (self.folder, str(e)))

def get_remote_url(self, remote="origin"):
remotes = self._run("remote -v")
for r in remotes.splitlines():
name, url = r.split(maxsplit=1)
if name == remote:
url, _ = url.rsplit(None, 1)
if os.path.exists(url): # Windows local directory
url = url.replace("\\", "/")
return url

def commit_in_remote(self, commit, remote="origin"):
if not remote:
return False
try:
branches = self._run("branch -r --contains {}".format(commit))
return "{}/".format(remote) in branches
except Exception as e:
raise ConanException("Unable to check remote commit in '%s': %s" % (self.folder, str(e)))

def is_dirty(self):
status = self._run("status -s").strip()
return bool(status)

def get_url_and_commit(self, remote="origin"):
dirty = self.is_dirty()
if dirty:
raise ConanException("Repo is dirty, cannot capture url and commit: "
"{}".format(self.folder))
commit = self.get_commit()
url = self.get_remote_url(remote=remote)
in_remote = self.commit_in_remote(commit, remote=remote)
if in_remote:
return url, commit
# TODO: Once we know how to pass [conf] to export, enable this
# conf_name = "tools.scm:local"
# allow_local = self._conanfile.conf[conf_name]
# if not allow_local:
# raise ConanException("Current commit {} doesn't exist in remote {}\n"
# "use '-c {}=1' to allow it".format(commit, remote, conf_name))

self._conanfile.output.warn("Current commit {} doesn't exist in remote {}\n"
"This revision will not be buildable in other "
"computer".format(commit, remote))
return self.get_repo_root(), commit

def get_repo_root(self):
folder = self._run("rev-parse --show-toplevel")
return folder.replace("\\", "/")

def clone(self, url, target=""):
if os.path.exists(url):
url = url.replace("\\", "/") # Windows local directory
mkdir(self.folder)
self._conanfile.output.info("Cloning git repo")
self._run('clone "{}" {}'.format(url, target))

def checkout(self, commit):
self._conanfile.output.info("Checkout: {}".format(commit))
self._run('checkout {}'.format(commit))
Empty file.
Loading