--- a/.hgtags Fri Sep 28 17:28:40 2012 +0200
+++ b/.hgtags Wed Aug 07 10:46:21 2013 +0200
@@ -78,3 +78,11 @@
372245c5bbb01a8f990c6eb2b9eed545ff6dba2b apycot-debian-version-2.2.2-1
5d1b7e01c4bcdfaf450493ad8964d8cd12854513 apycot-version-2.2.3
ae91a0cc488e612bdf5da1905db6028544bf3641 apycot-debian-version-2.2.3-1
+ff4868ee734fd14083a7f41799f00f87b66b28ac apycot-version-2.2.4
+0705ec800c172f3437ff30a71ce2f800f014a37a apycot-debian-version-2.2.4-1
+03c81aef4a704389512cf8ace75f6fcce0fbd3b5 apycot-version-2.2.5
+03c81aef4a704389512cf8ace75f6fcce0fbd3b5 apycot-debian-version-2.2.5-1
+c727a537bae157c6cb7e8ad429aeff2b294cafa5 apycot-version-2.2.6
+f910f242383076525c4da31221abed8443c086c9 apycot-debian-version-2.2.6-1
+7e2fab53d5c80955e8fb2383a93d2b64a5d151f3 apycot-version-2.2.7
+00a869904b15eda95b4b86bf81f32cabfecba462 apycot-debian-version-2.2.7-1
--- a/__pkginfo__.py Fri Sep 28 17:28:40 2012 +0200
+++ b/__pkginfo__.py Wed Aug 07 10:46:21 2013 +0200
@@ -4,7 +4,7 @@
modname = 'apycot'
distname = 'apycot'
-numversion = (2, 2, 3)
+numversion = (2, 2, 7)
version = '.'.join(str(num) for num in numversion)
license = 'GPL'
@@ -21,7 +21,7 @@
__depends__ = {'pyro': None,
'cubicweb': '>= 3.14.0',
- 'cubicweb-vcsfile': '>= 1.6.1',
+ 'cubicweb-vcsfile': '>= 1.12',
'cubicweb-file': None,
'cubicweb-narval': '>= 3.0.2',
}
--- a/_apycotlib/atest.py Fri Sep 28 17:28:40 2012 +0200
+++ b/_apycotlib/atest.py Wed Aug 07 10:46:21 2013 +0200
@@ -92,6 +92,7 @@
self._failed_pp = set()
self.executed_checkers = {}
self.global_status = SUCCESS
+ os.umask(022)
def __str__(self):
return repr(self.apycot_repository())
@@ -121,6 +122,8 @@
return self._repositories[pe.eid]
except KeyError:
from apycotlib.repositories import get_repository
+ if not pe.repository:
+ raise Exception('Project environment %s has no repository' % pe.dc_title())
repdef = {'repository': pe.repository,
'path': pe.vcs_path,
'branch': self.branch}
--- a/_apycotlib/checkers/python.py Fri Sep 28 17:28:40 2012 +0200
+++ b/_apycotlib/checkers/python.py Wed Aug 07 10:46:21 2013 +0200
@@ -55,9 +55,9 @@
if not modname and exists(join(test.tmpdir, test.project_path(), '__pkginfo__.py')):
from logilab.devtools.lib.pkginfo import PackageInfo
pkginfo = PackageInfo(directory=test.project_path())
- modname = getattr(pkginfo, 'modname', None)
- distname = getattr(pkginfo, 'distname', modname)
- package = getattr(pkginfo, 'subpackage_of', None)
+ modname = pkginfo.modname
+ distname = pkginfo.distname or modname
+ package = pkginfo.subpackage_of
if modname and package:
modname = '%s.%s' % (package, modname)
elif distname.startswith('cubicweb-'):
--- a/_apycotlib/preprocessors/distutils.py Fri Sep 28 17:28:40 2012 +0200
+++ b/_apycotlib/preprocessors/distutils.py Wed Aug 07 10:46:21 2013 +0200
@@ -64,7 +64,7 @@
pyversions_.append(python)
pyversions = pyversions_
else:
- pyversions = [sys.executable]
+ pyversions = ['python%s.%s' % sys.version_info[:2]]
return pyversions
INSTALL_PREFIX = {}
@@ -116,22 +116,14 @@
return
if not exists(join(path, 'setup.py')):
raise SetupException('No file %s' % abspath(join(path, 'setup.py')))
- # XXX need better detection of C extension
- if glob(join(path, '*.c')) or glob(join(path, '*.cpp')):
- pythons = pyversions(test) or [sys.executable]
- installopt = '--prefix'
- INSTALL_PREFIX[path] = join(test.tmpdir, 'local', 'lib', pythons[0])
- else:
- pythons = (pyversions(test) or [sys.executable])[0],
- installopt = '--home'
- INSTALL_PREFIX[path] = join(test.tmpdir, 'local', 'lib', 'python')
- for python in pythons:
- cmdargs = [python, 'setup.py', 'install', installopt,
- join(test.tmpdir, 'local')]
- if not self.options.get('verbose'):
- cmdargs.append('--quiet')
- cmd = Command(self.writer, cmdargs, raises=True, cwd=path)
- cmd.run()
+ python = pyversions(test)[0]
+ INSTALL_PREFIX[path] = join(test.tmpdir, 'local', 'lib', 'python')
+ cmdargs = [python, 'setup.py', 'install', '--home',
+ join(test.tmpdir, 'local')]
+ if not self.options.get('verbose'):
+ cmdargs.append('--quiet')
+ cmd = Command(self.writer, cmdargs, raises=True, cwd=path)
+ cmd.run()
if exists(join(path, 'build')):
shutil.rmtree(join(path, 'build')) # remove the build directory
--- a/_apycotlib/repositories.py Fri Sep 28 17:28:40 2012 +0200
+++ b/_apycotlib/repositories.py Wed Aug 07 10:46:21 2013 +0200
@@ -172,13 +172,14 @@
package
"""
if quiet:
- return 'hg clone -q %s' % self.ref_repo
- return 'hg clone %s' % self.ref_repo
+ return "hg clone -q %s && hg -R %s up '::. and public()'" % (self.ref_repo, self.co_path)
+ return "hg clone %s && hg -R %s up '::. and public()'" % (self.ref_repo, self.co_path)
def co_move_to_branch_command(self, quiet=True):
- # if branch doesn't exists, stay in default
+ # if branch doesn't exist, stay in default
if self.branch:
- return 'hg -R %s up %s' % (self.co_path, self.branch)
+ return "hg -R %s up 'first(id(%s) + max(branch(%s) and public()))'" % (
+ self.co_path, self.branch, self.branch)
return None
def changeset(self):
--- a/_apycotlib/writer.py Fri Sep 28 17:28:40 2012 +0200
+++ b/_apycotlib/writer.py Wed Aug 07 10:46:21 2013 +0200
@@ -132,8 +132,9 @@
print msg
def _log(self, severity, path, line, msg):
- encodedmsg = u'%s\t%s\t%s\t%s<br/>' % (severity, path or u'',
- line or u'', xml_escape(msg))
+ encodedmsg = u'%s\t%s\t%s\t%s<br/>' % (severity, xml_escape(path or u''),
+ xml_escape(u'%s' % (line or u'')),
+ xml_escape(msg))
self._logs.append(encodedmsg)
def raw(self, name, value, type=None, commit=True):
@@ -204,7 +205,8 @@
if not self._cnxh.execute(
'SET X using_revision REV '
'WHERE X eid %(x)s, REV changeset %(cs)s, '
- 'REV from_repository R, R eid %(r)s',
+ 'REV from_repository R, R eid %(r)s, '
+ 'NOT X using_revision REV',
{'x': self._eid, 'cs': changeset,
'r': environment.repository.eid}):
self.raw(repr(vcsrepo), changeset, 'revision')
--- a/debian/changelog Fri Sep 28 17:28:40 2012 +0200
+++ b/debian/changelog Wed Aug 07 10:46:21 2013 +0200
@@ -1,3 +1,27 @@
+apycot (2.2.7-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Julien Cristau <julien.cristau@logilab.fr> Mon, 10 Jun 2013 16:19:54 +0200
+
+apycot (2.2.6-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- David Douard <david.douard@logilab.fr> Thu, 02 May 2013 10:15:52 +0200
+
+apycot (2.2.5-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- David Douard <david.douard@logilab.fr> Tue, 09 Apr 2013 15:10:53 +0200
+
+apycot (2.2.4-1) unstable; urgency=low
+
+ * new upstream release
+
+ -- David Douard <david.douard@logilab.fr> Fri, 25 Jan 2013 23:08:10 +0100
+
apycot (2.2.3-1) unstable; urgency=low
* new upstream release
--- a/debian/control Fri Sep 28 17:28:40 2012 +0200
+++ b/debian/control Wed Aug 07 10:46:21 2013 +0200
@@ -13,7 +13,7 @@
Package: cubicweb-apycot
Architecture: all
XB-Python-Version: ${python:Versions}
-Depends: ${misc:Depends}, ${python:Depends}, cubicweb-common (>= 3.14.0), cubicweb-vcsfile (>= 1.6.1), cubicweb-file (>= 1.8.2), cubicweb-narval (>= 3.0.2), pyro
+Depends: ${misc:Depends}, ${python:Depends}, cubicweb-common (>= 3.14.0), cubicweb-vcsfile (>= 1.12), cubicweb-file (>= 1.8.2), cubicweb-narval (>= 3.0.2), pyro
Recommends: cubicweb-jqplot (>= 0.1.2)
Suggests: cubicweb-tracker, cubicweb-nosylist (>= 0.5.0)
Description: apycot component for the CubicWeb framework
--- a/hooks.py Fri Sep 28 17:28:40 2012 +0200
+++ b/hooks.py Wed Aug 07 10:46:21 2013 +0200
@@ -122,6 +122,64 @@
self.repo.looping_task(60*60, check_test_to_start, self.repo)
+class StartTestOp(hook.DataOperationMixIn, hook.Operation):
+ def precommit_event(self):
+ for revision in self.get_data():
+ vcsrepo = revision.repository
+ for basepe in vcsrepo.reverse_local_repository:
+ for pe in basepe.iter_refinements():
+ if pe.vcs_path:
+ # start test only if the revision is modifying file under
+ # specified directory.
+ if not self.session.execute(
+ 'Any R LIMIT 1 WHERE R eid %(r)s, VC from_revision R,'
+ 'VC content_for VF, VF directory ~= %(path)s',
+ {'r': revision.eid, 'path': pe.vcs_path + '%'}):
+ continue
+ for tc in pe.iter_configurations('on new revision'):
+ if tc.match_branch(pe, revision.branch):
+ # check recipe, we don't want buggy config to block
+ # creation of the revision
+ if tc.recipe:
+ tc.start(pe, revision.branch)
+ else:
+ self.error('expected to start test config %s for '
+ 'revision with %s but it has no recipe',
+ tc, revision)
+ # when a test is started, it may use some revision of dependency's
+ # repositories that may not be already imported by vcsfile. So when it
+ # try to create a link between the execution and the revision, it
+ # fails. In such case the information is kept as a CheckResultInfo
+ # object, use it to create the link later when the changeset is
+ # imported.
+ done = set(x.eid for x in revision.reverse_using_revision)
+ for cri in self.session.execute(
+ 'Any CRI, X WHERE CRI for_check X, CRI type "revision", '
+ 'CRI label ~= %(repo)s, CRI value %(cs)s',
+ {'cs': revision.changeset,
+ # safety belt in case of duplicated short changeset. XXX useful?
+ 'repo': '%s:%s%%' % (vcsrepo.type, vcsrepo.source_url or vcsrepo.path),
+ }).entities():
+ # safety belt to avoid crash if relation is already set. In some
+ # dark cases we end up with several version information about the
+ # same project on the same check result...
+ if cri.check_result.eid not in done:
+ cri.check_result.set_relations(using_revision=revision)
+ done.add(cri.check_result.eid)
+ cri.cw_delete()
+
+
+class StartTestAfterPublicRevision(hook.Hook):
+ __regid__ = 'apycot.start_test_on_public_rev'
+ __select__ = hook.Hook.__select__ & is_instance('Revision') & ~session.repairing()
+ events = ('before_update_entity',)
+
+ def __call__(self):
+ revision = self.entity
+ if 'phase' not in revision.cw_edited or revision.cw_edited['phase'] != 'public':
+ return
+ StartTestOp.get_instance(self._cw).add_data(revision)
+
class StartTestAfterAddRevision(hook.Hook):
__regid__ = 'apycot.start_test_on_new_rev'
__select__ = hook.Hook.__select__ & is_instance('Revision') & ~session.repairing()
@@ -129,48 +187,9 @@
def __call__(self):
revision = self.entity
- vcsrepo = revision.repository
- for basepe in vcsrepo.reverse_local_repository:
- for pe in basepe.iter_refinements():
- if pe.vcs_path:
- # start test only if the revision is modifying file under
- # specified directory.
- if not self._cw.execute(
- 'Any R LIMIT 1 WHERE R eid %(r)s, VC from_revision R,'
- 'VC content_for VF, VF directory ~= %(path)s',
- {'r': revision.eid, 'path': pe.vcs_path + '%'}):
- continue
- for tc in pe.iter_configurations('on new revision'):
- if tc.match_branch(pe, revision.branch):
- # check recipe, we don't want buggy config to block
- # creation of the revision
- if tc.recipe:
- tc.start(pe, revision.branch)
- else:
- self.error('expected to start test config %s for '
- 'revision with %s but it has no recipe',
- tc, revision)
- # when a test is started, it may use some revision of dependency's
- # repositories that may not be already imported by vcsfile. So when it
- # try to create a link between the execution and the revision, it
- # fails. In such case the information is kept as a CheckResultInfo
- # object, use it to create the link later when the changeset is
- # imported.
- done = set()
- for cri in self._cw.execute(
- 'Any CRI, X WHERE CRI for_check X, CRI type "revision", '
- 'CRI label ~= %(repo)s, CRI value %(cs)s',
- {'cs': revision.changeset,
- # safety belt in case of duplicated short changeset. XXX useful?
- 'repo': '%s:%s%%' % (vcsrepo.type, vcsrepo.source_url or vcsrepo.path),
- }).entities():
- # safety belt to avoid crash if relation is already set. In some
- # dark cases we end up with several version information about the
- # same project on the same check result...
- if cri.check_result.eid not in done:
- cri.check_result.set_relations(using_revision=revision)
- done.add(cri.check_result.eid)
- cri.cw_delete()
+ if revision.phase != 'public':
+ return
+ StartTestOp.get_instance(self._cw).add_data(revision)
# notifications ################################################################
--- a/test/unittest_task.py Fri Sep 28 17:28:40 2012 +0200
+++ b/test/unittest_task.py Wed Aug 07 10:46:21 2013 +0200
@@ -14,7 +14,6 @@
from apycotlib.atest import Test as BaseTest
from apycotlib.repositories import SVNRepository
-
# manage temporary repo
def setUpModule():
for repo in ('badpkg2_svn', 'goodpkg_svn'):
@@ -98,6 +97,9 @@
def apycot_process_environment(self):
return {}
+ def dc_title(self):
+ return self.name
+
# mock objects ################################################################
class CleanRaisePreprocessor:
@@ -378,6 +380,13 @@
# default should be the branch name (as none is defined)
self.assertEqual(repo.branch, 'default')
+ def test_missing_repo(self):
+ dep = Environment('babar', repository=None)
+ test = Test(TestConfig('yo', dependencies=(dep,)),
+ MockTestWriter(), {},
+ checkers=[SuccessTestChecker()])
+ self.assertRaises(Exception, test.apycot_repository, dep)
+
class EnvironmentTrackerMixinTC(TestCase):
--- a/views/__init__.py Fri Sep 28 17:28:40 2012 +0200
+++ b/views/__init__.py Wed Aug 07 10:46:21 2013 +0200
@@ -9,8 +9,6 @@
from cubicweb.web.views import urlpublishing
from cubicweb.web.views.urlrewrite import rgx, build_rset, SchemaBasedRewriter
-from cubes.narval.proxy import bot_proxy
-
_afs = uicfg.autoform_section
_affk = uicfg.autoform_field_kwargs
@@ -22,7 +20,6 @@
_affk.tag_attribute(('ProjectEnvironment', 'vcs_path'),
{'widget': wdgs.TextInput})
-_afs.tag_subject_of(('ProjectEnvironment', 'local_repository', '*'), 'main', 'inlined')
_afs.tag_object_of(('*', 'for_environment', 'ProjectEnvironment'), 'main', 'relations')
_affk.tag_attribute(('TestConfig', 'start_mode'), {'sort': False})
--- a/views/primary.py Fri Sep 28 17:28:40 2012 +0200
+++ b/views/primary.py Wed Aug 07 10:46:21 2013 +0200
@@ -135,9 +135,10 @@
html_headers = no_robot_index
def entity_call(self, entity):
- project_rset = self._cw.execute('Any P WHERE P has_apycot_environment TC, TC eid %(e)s',
- {'e': entity.eid})
- self.wview('projectgraphtestresults', project_rset, 'null')
+ if 'jqplot' in self._cw.vreg.config.cubes():
+ project_rset = self._cw.execute('Any P WHERE P has_apycot_environment TC, TC eid %(e)s',
+ {'e': entity.eid})
+ self.wview('projectgraphtestresults', project_rset, 'null')
rset = self._cw.execute(
'Any T,TC,T,TB,TST,TET,TF, TS ORDERBY TST DESC WHERE '
'T status TS, T using_config TC, T branch TB, '
--- a/views/tracker.py Fri Sep 28 17:28:40 2012 +0200
+++ b/views/tracker.py Wed Aug 07 10:46:21 2013 +0200
@@ -99,7 +99,8 @@
__select__ = is_instance('Project')
def entity_call(self, entity):
- self.wview('projectgraphtestresults', self.cw_rset, 'null')
+ if 'jqplot' in self._cw.vreg.config.cubes():
+ self.wview('projectgraphtestresults', self.cw_rset, 'null')
rset = self._cw.execute(
'Any T,TC,T,TB,TST,TET,TF, TS ORDERBY TST DESC WHERE '
'T status TS, T using_config TC, T branch TB, '