merge from stable
authorDavid Douard <david.douard@logilab.fr>
Wed, 07 Aug 2013 10:46:21 +0200
changeset 1005 0dff68de958e
parent 832 fbb7eb24f3ad (current diff)
parent 923 478b60e0e112 (diff)
child 1006 e50f134e41b7
merge from stable
--- 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, '