changeset 2684:2b6939a77052 beta

Bumped mercurial version to 2.3 - fixed issues with compare of two remote repos at particular revisions - added tests for cases when mercurial update broke code and tests didn't catch this - removed obsolete EmptyChangeset from the rhodecode code
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 04 Aug 2012 01:20:38 +0200
parents eaf1782bee64
children 4a7a9f2c1dba
files rhodecode/controllers/changeset.py rhodecode/controllers/compare.py rhodecode/controllers/files.py rhodecode/controllers/summary.py rhodecode/lib/diffs.py rhodecode/lib/utils.py rhodecode/lib/utils2.py rhodecode/lib/vcs/utils/hgcompat.py rhodecode/model/pull_request.py rhodecode/model/scm.py rhodecode/tests/functional/test_compare.py
diffstat 11 files changed, 183 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/changeset.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/controllers/changeset.py	Sat Aug 04 01:20:38 2012 +0200
@@ -40,7 +40,7 @@
 import rhodecode.lib.helpers as h
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 from rhodecode.lib.base import BaseRepoController, render
-from rhodecode.lib.utils import EmptyChangeset, action_logger
+from rhodecode.lib.utils import action_logger
 from rhodecode.lib.compat import OrderedDict
 from rhodecode.lib import diffs
 from rhodecode.model.db import ChangesetComment, ChangesetStatus
@@ -50,6 +50,7 @@
 from rhodecode.lib.diffs import wrapped_diff
 from rhodecode.model.repo import RepoModel
 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
 log = logging.getLogger(__name__)
 
--- a/rhodecode/controllers/compare.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/controllers/compare.py	Sat Aug 04 01:20:38 2012 +0200
@@ -71,6 +71,7 @@
             redirect(url('summary_home', repo_name=repo.repo_name))
 
         except RepositoryError, e:
+            log.error(traceback.format_exc())
             h.flash(str(e), category='warning')
             redirect(h.url('summary_home', repo_name=repo.repo_name))
 
--- a/rhodecode/controllers/files.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/controllers/files.py	Sat Aug 04 01:20:38 2012 +0200
@@ -40,7 +40,7 @@
 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 from rhodecode.lib.base import BaseRepoController, render
-from rhodecode.lib.utils import EmptyChangeset
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 from rhodecode.lib.vcs.conf import settings
 from rhodecode.lib.vcs.exceptions import RepositoryError, \
     ChangesetDoesNotExistError, EmptyRepositoryError, \
--- a/rhodecode/controllers/summary.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/controllers/summary.py	Sat Aug 04 01:20:38 2012 +0200
@@ -45,7 +45,7 @@
 from rhodecode.lib.utils2 import safe_unicode
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 from rhodecode.lib.base import BaseRepoController, render
-from rhodecode.lib.utils import EmptyChangeset
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 from rhodecode.lib.markup_renderer import MarkupRenderer
 from rhodecode.lib.celerylib import run_task
 from rhodecode.lib.celerylib.tasks import get_commits_stats
--- a/rhodecode/lib/diffs.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/lib/diffs.py	Sat Aug 04 01:20:38 2012 +0200
@@ -34,15 +34,16 @@
 from mercurial import patch
 from mercurial.mdiff import diffopts
 from mercurial.bundlerepo import bundlerepository
-from mercurial import localrepo
 
 from pylons.i18n.translation import _
 
 from rhodecode.lib.compat import BytesIO
+from rhodecode.lib.vcs.utils.hgcompat import localrepo
 from rhodecode.lib.vcs.exceptions import VCSError
 from rhodecode.lib.vcs.nodes import FileNode, SubModuleNode
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 from rhodecode.lib.helpers import escape
-from rhodecode.lib.utils import EmptyChangeset, make_ui
+from rhodecode.lib.utils import make_ui
 
 
 def wrap_to_table(str_):
@@ -599,9 +600,9 @@
     if org_repo != other_repo:
 
         common, incoming, rheads = discovery_data
-
+        other_repo_peer = localrepo.locallegacypeer(other_repo.local())
         # create a bundle (uncompressed if other repo is not local)
-        if other_repo.capable('getbundle') and incoming:
+        if other_repo_peer.capable('getbundle') and incoming:
             # disable repo hooks here since it's just bundle !
             # patch and reset hooks section of UI config to not run any
             # hooks on fetching archives with subrepos
--- a/rhodecode/lib/utils.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/lib/utils.py	Sat Aug 04 01:20:38 2012 +0200
@@ -346,50 +346,6 @@
         ScmModel().mark_for_invalidation(name)
 
 
-class EmptyChangeset(BaseChangeset):
-    """
-    An dummy empty changeset. It's possible to pass hash when creating
-    an EmptyChangeset
-    """
-
-    def __init__(self, cs='0' * 40, repo=None, requested_revision=None,
-                 alias=None):
-        self._empty_cs = cs
-        self.revision = -1
-        self.message = ''
-        self.author = ''
-        self.date = ''
-        self.repository = repo
-        self.requested_revision = requested_revision
-        self.alias = alias
-
-    @LazyProperty
-    def raw_id(self):
-        """
-        Returns raw string identifying this changeset, useful for web
-        representation.
-        """
-
-        return self._empty_cs
-
-    @LazyProperty
-    def branch(self):
-        return get_backend(self.alias).DEFAULT_BRANCH_NAME
-
-    @LazyProperty
-    def short_id(self):
-        return self.raw_id[:12]
-
-    def get_file_changeset(self, path):
-        return self
-
-    def get_file_content(self, path):
-        return u''
-
-    def get_file_size(self, path):
-        return 0
-
-
 def map_groups(path):
     """
     Given a full path to a repository, create all nested groups that this
--- a/rhodecode/lib/utils2.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/lib/utils2.py	Sat Aug 04 01:20:38 2012 +0200
@@ -417,6 +417,7 @@
     """
     from rhodecode.lib.vcs.backends.base import BaseRepository
     from rhodecode.lib.vcs.exceptions import RepositoryError
+    from rhodecode.lib.vcs.backends.base import EmptyChangeset
     if not isinstance(repo, BaseRepository):
         raise Exception('You must pass an Repository '
                         'object as first argument got %s', type(repo))
@@ -424,7 +425,6 @@
     try:
         cs = repo.get_changeset(rev)
     except RepositoryError:
-        from rhodecode.lib.utils import EmptyChangeset
         cs = EmptyChangeset(requested_revision=rev)
     return cs
 
--- a/rhodecode/lib/vcs/utils/hgcompat.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/lib/vcs/utils/hgcompat.py	Sat Aug 04 01:20:38 2012 +0200
@@ -13,3 +13,5 @@
 from mercurial.node import hex
 from mercurial.encoding import tolocal
 from mercurial import discovery
+from mercurial import localrepo
+from mercurial import scmutil
\ No newline at end of file
--- a/rhodecode/model/pull_request.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/model/pull_request.py	Sat Aug 04 01:20:38 2012 +0200
@@ -36,7 +36,7 @@
 from rhodecode.model.notification import NotificationModel
 from rhodecode.lib.utils2 import safe_unicode
 
-from rhodecode.lib.vcs.utils.hgcompat import discovery
+from rhodecode.lib.vcs.utils.hgcompat import discovery, localrepo, scmutil
 
 log = logging.getLogger(__name__)
 
@@ -150,13 +150,9 @@
         """
         changesets = []
         #case two independent repos
-        if org_repo != other_repo:
-            common, incoming, rheads = discovery_data
-
-            if not incoming:
-                revs = []
-            else:
-                revs = org_repo._repo.changelog.findmissing(common, rheads)
+        common, incoming, rheads = discovery_data
+        if org_repo != other_repo and incoming:
+            revs = org_repo._repo.changelog.findmissing(common, rheads)
 
             for cs in reversed(map(binascii.hexlify, revs)):
                 changesets.append(org_repo.get_changeset(cs))
@@ -175,7 +171,6 @@
                )
             ]
 
-            from mercurial import scmutil
             out = scmutil.revrange(org_repo._repo, revs)
             for cs in reversed(out):
                 changesets.append(org_repo.get_changeset(cs))
@@ -197,17 +192,22 @@
         :type other_ref:
         """
 
-        other = org_repo._repo
-        repo = other_repo._repo
-        tip = other[org_ref[1]]
+        _org_repo = org_repo._repo
+        org_rev_type, org_rev = org_ref
+
+        _other_repo = other_repo._repo
+        other_rev_type, other_rev = other_ref
+
         log.debug('Doing discovery for %s@%s vs %s@%s' % (
                         org_repo, org_ref, other_repo, other_ref)
         )
-        log.debug('Filter heads are %s[%s]' % (tip, org_ref[1]))
+        #log.debug('Filter heads are %s[%s]' % ('', org_ref[1]))
+        org_peer = localrepo.locallegacypeer(_org_repo.local())
         tmp = discovery.findcommonincoming(
-                  repo=repo,  # other_repo we check for incoming
-                  remote=other,  # org_repo source for incoming
-                  heads=[tip.node()],
+                  repo=_other_repo,  # other_repo we check for incoming
+                  remote=org_peer,  # org_repo source for incoming
+                  heads=[_other_repo[other_rev].node(),
+                         _org_repo[org_rev].node()],
                   force=False
         )
         return tmp
@@ -237,8 +237,9 @@
                                            other_repo.scm_instance,
                                            other_ref)
         cs_ranges = self._get_changesets(org_repo.scm_instance,
-                                           org_ref,
-                                           other_repo.scm_instance,
-                                           other_ref,
-                                           discovery_data)
+                                         org_ref,
+                                         other_repo.scm_instance,
+                                         other_ref,
+                                         discovery_data)
+
         return cs_ranges, discovery_data
--- a/rhodecode/model/scm.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/model/scm.py	Sat Aug 04 01:20:38 2012 +0200
@@ -40,13 +40,14 @@
 from rhodecode.lib.vcs.exceptions import RepositoryError
 from rhodecode.lib.vcs.utils.lazy import LazyProperty
 from rhodecode.lib.vcs.nodes import FileNode
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
 from rhodecode import BACKENDS
 from rhodecode.lib import helpers as h
 from rhodecode.lib.utils2 import safe_str, safe_unicode
 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
-    action_logger, EmptyChangeset, REMOVED_REPO_PAT
+    action_logger, REMOVED_REPO_PAT
 from rhodecode.model import BaseModel
 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
     UserFollowing, UserLog, User, RepoGroup, PullRequest
@@ -414,6 +415,12 @@
 
     def commit_change(self, repo, repo_name, cs, user, author, message,
                       content, f_path):
+        """
+        Commits changes
+
+        :param repo: SCM instance
+
+        """
 
         if repo.alias == 'hg':
             from rhodecode.lib.vcs.backends.hg import \
@@ -439,6 +446,7 @@
         action = 'push_local:%s' % tip.raw_id
         action_logger(user, action, repo_name)
         self.mark_for_invalidation(repo_name)
+        return tip
 
     def create_node(self, repo, repo_name, cs, user, author, message, content,
                       f_path):
@@ -477,6 +485,7 @@
         action = 'push_local:%s' % tip.raw_id
         action_logger(user, action, repo_name)
         self.mark_for_invalidation(repo_name)
+        return tip
 
     def get_nodes(self, repo_name, revision, root_path='/', flat=True):
         """
--- a/rhodecode/tests/functional/test_compare.py	Fri Aug 03 23:07:26 2012 +0200
+++ b/rhodecode/tests/functional/test_compare.py	Sat Aug 04 01:20:38 2012 +0200
@@ -1,12 +1,17 @@
 from rhodecode.tests import *
+from rhodecode.model.repo import RepoModel
+from rhodecode.model.meta import Session
+from rhodecode.model.db import Repository
+from rhodecode.model.scm import ScmModel
+from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
 
 class TestCompareController(TestController):
 
     def test_index_tag(self):
         self.log_user()
-        tag1='0.1.3'
-        tag2='0.1.2'
+        tag1 = '0.1.3'
+        tag2 = '0.1.2'
         response = self.app.get(url(controller='compare', action='index',
                                     repo_name=HG_REPO,
                                     org_ref_type="tag",
@@ -50,3 +55,135 @@
         response.mustcontain('%s@default -> %s@default' % (HG_REPO, HG_REPO))
         # branch are equal
         response.mustcontain('<tr><td>No changesets</td></tr>')
+
+    def test_compare_revisions(self):
+        self.log_user()
+        rev1 = '3d8f361e72ab'
+        rev2 = 'b986218ba1c9'
+        response = self.app.get(url(controller='compare', action='index',
+                                    repo_name=HG_REPO,
+                                    org_ref_type="rev",
+                                    org_ref=rev1,
+                                    other_ref_type="rev",
+                                    other_ref=rev2,
+                                    ))
+        response.mustcontain('%s@%s -> %s@%s' % (HG_REPO, rev1, HG_REPO, rev2))
+        ## outgoing changesets between those revisions
+        response.mustcontain("""<a href="/%s/changeset/3d8f361e72ab303da48d799ff1ac40d5ac37c67e">r1:%s</a>""" % (HG_REPO, rev1))
+
+        ## files
+        response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--c8e92ef85cd1">.hgignore</a>""" % (HG_REPO, rev1, rev2))
+
+    def test_compare_remote_repos(self):
+        self.log_user()
+
+        form_data = dict(
+            repo_name=HG_FORK,
+            repo_name_full=HG_FORK,
+            repo_group=None,
+            repo_type='hg',
+            description='',
+            private=False,
+            copy_permissions=False,
+            landing_rev='tip',
+            update_after_clone=False,
+            fork_parent_id=Repository.get_by_repo_name(HG_REPO),
+        )
+        RepoModel().create_fork(form_data, cur_user=TEST_USER_ADMIN_LOGIN)
+
+        Session().commit()
+
+        rev1 = '7d4bc8ec6be5'
+        rev2 = '56349e29c2af'
+
+        response = self.app.get(url(controller='compare', action='index',
+                                    repo_name=HG_REPO,
+                                    org_ref_type="rev",
+                                    org_ref=rev1,
+                                    other_ref_type="rev",
+                                    other_ref=rev2,
+                                    repo=HG_FORK
+                                    ))
+
+        try:
+            response.mustcontain('%s@%s -> %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
+            ## outgoing changesets between those revisions
+
+            response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_REPO, rev1))
+            response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_REPO))
+            response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_REPO))
+
+            ## files
+            response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2))
+            response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2))
+            response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2))
+        finally:
+            RepoModel().delete(HG_FORK)
+
+    def test_compare_extra_commits(self):
+        self.log_user()
+
+        repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
+                                        description='diff-test',
+                                        owner=TEST_USER_ADMIN_LOGIN)
+
+        repo2 = RepoModel().create_repo(repo_name='one-fork', repo_type='hg',
+                                        description='diff-test',
+                                        owner=TEST_USER_ADMIN_LOGIN)
+
+        Session().commit()
+        r1_id = repo1.repo_id
+        r1_name = repo1.repo_name
+        r2_id = repo2.repo_id
+        r2_name = repo2.repo_name
+
+        #commit something !
+        cs0 = ScmModel().create_node(
+            repo=repo1.scm_instance, repo_name=r1_name,
+            cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
+            author=TEST_USER_ADMIN_LOGIN,
+            message='commit1',
+            content='line1',
+            f_path='file1'
+        )
+
+        cs0_prim = ScmModel().create_node(
+            repo=repo2.scm_instance, repo_name=r2_name,
+            cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
+            author=TEST_USER_ADMIN_LOGIN,
+            message='commit1',
+            content='line1',
+            f_path='file1'
+        )
+
+        cs1 = ScmModel().commit_change(
+            repo=repo2.scm_instance, repo_name=r2_name,
+            cs=cs0_prim, user=TEST_USER_ADMIN_LOGIN, author=TEST_USER_ADMIN_LOGIN,
+            message='commit2',
+            content='line1\nline2',
+            f_path='file1'
+        )
+
+        rev1 = 'default'
+        rev2 = 'default'
+        response = self.app.get(url(controller='compare', action='index',
+                                    repo_name=r2_name,
+                                    org_ref_type="branch",
+                                    org_ref=rev1,
+                                    other_ref_type="branch",
+                                    other_ref=rev2,
+                                    repo=r1_name
+                                    ))
+
+        try:
+            response.mustcontain('%s@%s -> %s@%s' % (r2_name, rev1, r1_name, rev2))
+
+            response.mustcontain("""<div class="message">commit2</div>""")
+            response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (r2_name, cs1.raw_id, cs1.short_id))
+            ## files
+            response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s#C--826e8142e6ba">file1</a>""" % (r2_name, rev1, rev2))
+
+
+        finally:
+            RepoModel().delete(r1_id)
+            RepoModel().delete(r2_id)