changeset 7675:c8239333853d

hooks: refactor log_push_action The core of the functionality is to process a list of "raw id"s, log them, and update / invalidate caches. handle_git_post_receive and scm _handle_push already provide that list directly. Things get much simpler when introducing a new function (process_pushed_raw_ids) just for processing pushed raw ids. That also makes it clear that scm _handle_push doesn't need any repo. log_push_action remains the native entry point for the Mercurial hook. It was not entirely correct using 'node:tip' - after Mercurial 3.7 and d6d3cf5fda6f, it should be 'node:node_last'. After several trivial refactorings, it turns out that the logic for creating the hash list for Mercurial actually is very simple ...
author Mads Kiilerich <mads@kiilerich.com>
date Wed, 16 Jan 2019 12:55:10 +0100
parents 5b551b189459
children 902cbe668001
files kallithea/lib/hooks.py kallithea/model/scm.py
diffstat 2 files changed, 31 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/lib/hooks.py	Wed Jan 23 00:03:40 2019 +0100
+++ b/kallithea/lib/hooks.py	Wed Jan 16 12:55:10 2019 +0100
@@ -82,6 +82,8 @@
     """Logs user last pull action
 
     Called as Mercurial hook outgoing.pull_logger or from Kallithea before invoking Git.
+
+    Does *not* use the action from the hook environment but is always 'pull'.
     """
     ex = _extract_extras()
 
@@ -99,43 +101,32 @@
     return 0
 
 
-def log_push_action(ui, repo, **kwargs):
+def log_push_action(ui, repo, node, node_last, **kwargs):
+    """
+    Entry point for Mercurial hook changegroup.push_logger.
+
+    The pushed changesets is given by the revset 'node:node_last'.
+
+    Note: This hook is not only logging, but also the side effect invalidating
+    cahes! The function should perhaps be renamed.
     """
-    Register that changes have been pushed - log it *and* invalidate caches.
-    Note: It is not only logging, but also the side effect invalidating cahes!
-    The function should perhaps be renamed.
+    _h = binascii.hexlify
+    revs = [_h(repo[r].node()) for r in revrange(repo, [node + ':' + node_last])]
+    process_pushed_raw_ids(revs)
+    return 0
+
 
-    Called as Mercurial hook changegroup.push_logger or from the Git
-    post-receive hook calling handle_git_post_receive ... or from scm _handle_push.
+def process_pushed_raw_ids(revs):
+    """
+    Register that changes have been added to the repo - log the action *and* invalidate caches.
 
-    Revisions are passed in different hack-ish ways.
+    Called from  Mercurial changegroup.push_logger calling hook log_push_action,
+    or from the Git post-receive hook calling handle_git_post_receive ...
+    or from scm _handle_push.
     """
     ex = _extract_extras()
 
-    action_tmpl = ex.action + ':%s'
-    revs = []
-    if ex.scm == 'hg':
-        node = kwargs['node']
-
-        def get_revs(repo, rev_opt):
-            if rev_opt:
-                revs = revrange(repo, rev_opt)
-
-                if len(revs) == 0:
-                    return (nullrev, nullrev)
-                return max(revs), min(revs)
-            else:
-                return len(repo) - 1, 0
-
-        stop, start = get_revs(repo, [node + ':'])
-        _h = binascii.hexlify
-        revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)]
-    elif ex.scm == 'git':
-        revs = kwargs.get('_git_revs', [])
-        if '_git_revs' in kwargs:
-            kwargs.pop('_git_revs')
-
-    action = action_tmpl % ','.join(revs)
+    action = '%s:%s' % (ex.action, ','.join(revs))
     action_logger(ex.username, action, ex.repository, ex.ip, commit=True)
 
     from kallithea.model.scm import ScmModel
@@ -149,8 +140,6 @@
         kw.update(ex)
         callback(**kw)
 
-    return 0
-
 
 def log_create_repository(repository_dict, created_by, **kwargs):
     """
@@ -348,6 +337,7 @@
 
 def handle_git_pre_receive(repo_path, git_stdin_lines):
     """Called from Git pre-receive hook"""
+    # Currently unused. TODO: remove?
     return 0
 
 
@@ -403,6 +393,6 @@
         elif _type == 'tags':
             git_revs += ['tag=>%s' % push_ref['name']]
 
-    log_push_action(baseui, scm_repo, _git_revs=git_revs)
+    process_pushed_raw_ids(git_revs)
 
     return 0
--- a/kallithea/model/scm.py	Wed Jan 23 00:03:40 2019 +0100
+++ b/kallithea/model/scm.py	Wed Jan 16 12:55:10 2019 +0100
@@ -55,7 +55,7 @@
     action_logger
 from kallithea.model.db import Repository, Session, Ui, CacheInvalidation, \
     UserFollowing, UserLog, User, RepoGroup, PullRequest
-from kallithea.lib.hooks import log_push_action
+from kallithea.lib.hooks import process_pushed_raw_ids
 from kallithea.lib.exceptions import NonRelativePathError, IMCCommitError
 
 log = logging.getLogger(__name__)
@@ -353,21 +353,17 @@
 
     def _handle_push(self, repo, username, action, repo_name, revisions):
         """
-        Triggers push action hooks
+        Handle that the repository has changed.
+        Adds an action log entry with the new revisions, and the head revision
+        cache and in-memory caches are invalidated/updated.
 
-        :param repo: SCM repo
         :param username: username who pushes
         :param action: push/push_local/push_remote
         :param repo_name: name of repo
         :param revisions: list of revisions that we pushed
         """
         self._handle_rc_scm_extras(username, repo_name, repo_alias=repo.alias, action=action)
-        _scm_repo = repo._repo
-        # trigger push hook
-        if repo.alias == 'hg':
-            log_push_action(_scm_repo.ui, _scm_repo, node=revisions[0])
-        elif repo.alias == 'git':
-            log_push_action(None, _scm_repo, _git_revs=revisions)
+        process_pushed_raw_ids(revisions) # also calls mark_for_invalidation
 
     def _get_IMC_module(self, scm_type):
         """
@@ -402,8 +398,8 @@
             if repo.alias == 'git':
                 repo.fetch(clone_uri)
                 # git doesn't really have something like post-fetch action
-                # we fake that now. #TODO: extract fetched revisions somehow
-                # here
+                # we fake that now.
+                # TODO: extract fetched revisions ... somehow ...
                 self._handle_push(repo,
                                   username=username,
                                   action='push_remote',