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

Avoid warning message from SVN check function #4264

Merged
merged 9 commits into from
Feb 28, 2019
9 changes: 5 additions & 4 deletions conans/client/cmd/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
from conans.client.file_copier import FileCopier
from conans.client.output import ScopedOutput
from conans.client.remover import DiskRemover
from conans.client.tools import Git, SVN
from conans.errors import ConanException
from conans.model.manifest import FileTreeManifest
from conans.model.scm import SCM, get_scm_data
from conans.model.scm import detect_repo_type
from conans.paths import CONANFILE
from conans.search.search import search_recipes, search_packages
from conans.util.files import is_dirty, load, mkdir, rmdir, save, set_dirty, remove
Expand Down Expand Up @@ -228,11 +226,14 @@ def _replace_scm_data_in_conanfile(conanfile_path, scm_data):


def _detect_scm_revision(path):
repo_type = detect_repo_type(path)
if not path:
return None, None

repo_type = SCM.detect_scm(path)
if not repo_type:
return None, None

repo_obj = {"git": Git, "svn": SVN}.get(repo_type)(path)
repo_obj = SCM.availables.get(repo_type)(path)
return repo_obj.get_revision(), repo_type


Expand Down
56 changes: 35 additions & 21 deletions conans/client/tools/scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,24 @@
from conans.util.files import decode_text, to_file_bytes, walk


def _run_muted(cmd, folder=None):
with chdir(folder) if folder else no_op():
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.communicate()
return process.returncode


def _check_repo(cmd, folder, msg=None):
msg = msg or "Not a valid '{}' repository".format(cmd[0])
try:
ret = _run_muted(cmd, folder=folder)
except Exception:
raise ConanException(msg)
else:
if bool(ret):
raise ConanException(msg)


class SCMBase(object):
cmd_command = None

Expand Down Expand Up @@ -90,7 +108,7 @@ def clone(self, url, branch=None, args=""):
return output

def checkout(self, element, submodule=None):
self._check_git_repo()
self.check_repo()
output = self.run('checkout "%s"' % element)

if submodule:
Expand Down Expand Up @@ -130,7 +148,7 @@ def excluded_files(self):
return ret

def get_remote_url(self, remote_name=None, remove_credentials=False):
self._check_git_repo()
self.check_repo()
remote_name = remote_name or "origin"
remotes = self.run("remote -v")
for remote in remotes.splitlines():
Expand All @@ -147,7 +165,7 @@ def is_local_repository(self):
return os.path.exists(url)

def get_commit(self):
self._check_git_repo()
self.check_repo()
try:
commit = self.run("rev-parse HEAD")
commit = commit.strip()
Expand All @@ -158,19 +176,19 @@ def get_commit(self):
get_revision = get_commit

def is_pristine(self):
self._check_git_repo()
self.check_repo()
status = self.run("status --porcelain").strip()
if not status:
return True
else:
return False

def get_repo_root(self):
self._check_git_repo()
self.check_repo()
return self.run("rev-parse --show-toplevel")

def get_branch(self):
self._check_git_repo()
self.check_repo()
try:
status = self.run("status -bs --porcelain")
# ## feature/scm_branch...myorigin/feature/scm_branch
Expand All @@ -180,19 +198,17 @@ def get_branch(self):
raise ConanException("Unable to get git branch from %s: %s" % (self.folder, str(e)))

def get_tag(self):
self._check_git_repo()
self.check_repo()
try:
status = self.run("describe --exact-match --tags")
tag = status.strip()
return tag
except Exception:
return None

def _check_git_repo(self):
try:
self.run("status")
except Exception:
raise ConanException("Not a valid git repository")
def check_repo(self):
""" Check if it is a valid GIT repo """
_check_repo(["git", "status"], folder=self.folder)


class SVN(SCMBase):
Expand Down Expand Up @@ -234,7 +250,7 @@ def run(self, command):
return super(SVN, self).run(command="{} {}".format(command, extra_options))

def _show_item(self, item, target='.'):
self._check_svn_repo()
self.check_repo()
if self.version >= SVN.API_CHANGE_VERSION:
value = self.run("info --show-item {item} \"{target}\"".format(item=item, target=target))
return value.strip()
Expand All @@ -260,7 +276,7 @@ def _show_item(self, item, target='.'):
def checkout(self, url, revision="HEAD"):
output = ""
try:
self._check_svn_repo()
self.check_repo()
except ConanException:
output += self.run('co "{url}" .'.format(url=url))
else:
Expand All @@ -272,11 +288,11 @@ def checkout(self, url, revision="HEAD"):
return output

def update(self, revision='HEAD'):
self._check_svn_repo()
self.check_repo()
return self.run("update -r {rev}".format(rev=revision))

def excluded_files(self):
self._check_svn_repo()
self.check_repo()
excluded_list = []
output = self.run("status --no-ignore")
for it in output.splitlines():
Expand Down Expand Up @@ -362,8 +378,6 @@ def _get_item(self, pattern, item_name):
item = re.search(pattern, url)
return item.group(0) if item else None

def _check_svn_repo(self):
try:
self.run("info")
except Exception:
raise ConanException("Not a valid SVN repository")
def check_repo(self):
""" Check if it is a valid SVN repo """
_check_repo(["svn", "info"], folder=self.folder)
38 changes: 13 additions & 25 deletions conans/model/scm.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import json
import os
import subprocess

from conans.client.tools.scm import Git, SVN
from conans.errors import ConanException
from conans.tools import chdir


def get_scm_data(conanfile):
Expand Down Expand Up @@ -52,38 +50,28 @@ def __repr__(self):
return json.dumps(d, sort_keys=True)


def detect_repo_type(folder):
if not folder:
return None

def _run_command_ignore_output(cmd):
with chdir(folder):
try:
ret = subprocess.call(cmd, shell=True,
stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT)
if ret != 0:
return False
except Exception:
return False
return True

if _run_command_ignore_output("git status"):
return "git"
elif _run_command_ignore_output("svn info"):
return "svn"
return None


class SCM(object):
availables = {'git': Git, 'svn': SVN}

def __init__(self, data, repo_folder, output):
self._data = data
self._output = output
self.repo_folder = repo_folder
# Finally instance a repo
self.repo = self._get_repo()

@classmethod
def detect_scm(cls, folder):
for name, candidate in cls.availables.items():
try:
candidate(folder).check_repo()
return name
except ConanException:
pass
return None

def _get_repo(self):
repo_class = {"git": Git, "svn": SVN}.get(self._data.type)
repo_class = self.availables.get(self._data.type)
if not repo_class:
raise ConanException("SCM not supported: %s" % self._data.type)

Expand Down
3 changes: 2 additions & 1 deletion conans/test/functional/scm/test_command_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def test_no_repo(self, repo_type, autos):
rev_value=rev_value)
})
self.client.run("export . lib/version@user/channel", assert_error=True)
self.assertIn("ERROR: Not a valid {} repository".format(repo_type), self.client.out)
self.assertIn("ERROR: Not a valid '{}' repository".format(repo_type.lower()),
self.client.out)


class ExportCommandTestCase(unittest.TestCase):
Expand Down
37 changes: 37 additions & 0 deletions conans/test/unittests/model/scm_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# coding=utf-8

import tempfile
import unittest

from mock import mock

from conans.errors import ConanException
from conans.model.scm import SCM


class SCMDetectRepoTest(unittest.TestCase):

def setUp(self):
self.folder = tempfile.gettempdir()
# Be sure there is no repo in the folder to test
for name, candidate in SCM.availables.items():
try:
candidate(folder=self.folder).check_repo()
except ConanException:
pass
else:
self.fail("There is a repo of type '{}' in the folder to test".format(name))

def test_svn(self):
with mock.patch("conans.client.tools.scm.SVN.check_repo", return_value=None):
r = SCM.detect_scm(folder=tempfile.gettempdir())
self.assertEqual(r, "svn")

def test_git(self):
with mock.patch("conans.client.tools.scm.Git.check_repo", return_value=None):
r = SCM.detect_scm(folder=tempfile.gettempdir())
self.assertEqual(r, "git")

def test_none(self):
r = SCM.detect_scm(folder=tempfile.gettempdir())
self.assertEqual(r, None)
16 changes: 15 additions & 1 deletion conans/test/unittests/util/tools_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1696,7 +1696,7 @@ def test_get_tag_no_git_repo(self):
Try to get tag out of a git repo
"""
git = Git(folder=temp_folder())
with self.assertRaisesRegexp(ConanException, "Not a valid git repository"):
with self.assertRaisesRegexp(ConanException, "Not a valid 'git' repository"):
git.get_tag()

def test_excluded_files(self):
Expand All @@ -1710,6 +1710,19 @@ def test_excluded_files(self):
@attr("slow")
@attr('svn')
class SVNToolTestsBasic(SVNLocalRepoTestCase):

def test_check_svn_repo(self):
project_url, _ = self.create_project(files={'myfile': "contents"})
tmp_folder = self.gimme_tmp()
svn = SVN(folder=tmp_folder)
with self.assertRaisesRegexp(ConanException, "Not a valid 'svn' repository"):
svn.check_repo()
svn.checkout(url=project_url)
try:
svn.check_repo()
except Exception:
self.fail("After checking out, it should be a valid SVN repository")

def test_clone(self):
project_url, _ = self.create_project(files={'myfile': "contents"})
tmp_folder = self.gimme_tmp()
Expand Down Expand Up @@ -1934,6 +1947,7 @@ def test_tag(self):
svn.get_tag()



@attr("slow")
@attr('svn')
class SVNToolTestsBasicOldVersion(SVNToolTestsBasic):
Expand Down