You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by jo...@apache.org on 2013/10/01 17:06:40 UTC

git commit: [#6686] Implement an indexless last_commit_ids for Git

Updated Branches:
  refs/heads/cj/6686 [created] 363e3a2f8


[#6686] Implement an indexless last_commit_ids for Git

NB: This is not fully indexless, since it still needs the model data for
controller dispatch and pulling the commit summary info (though the
later could easily be gotten from git while getting the last_commit_ids
just by changing the pretty=format param, it would just require more
refactoring to surface / cache it).

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/363e3a2f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/363e3a2f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/363e3a2f

Branch: refs/heads/cj/6686
Commit: 363e3a2f887ede99d22fa6928cb95e11044c9843
Parents: 182a724
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Tue Oct 1 14:52:00 2013 +0000
Committer: Cory Johns <cj...@slashdotmedia.com>
Committed: Tue Oct 1 15:06:19 2013 +0000

----------------------------------------------------------------------
 ForgeGit/forgegit/model/git_repo.py             | 42 ++++++++++++++++++++
 .../forgegit/tests/model/test_repository.py     | 14 +++++++
 2 files changed, 56 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/363e3a2f/ForgeGit/forgegit/model/git_repo.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py
index 29af6c7..938dc8a 100644
--- a/ForgeGit/forgegit/model/git_repo.py
+++ b/ForgeGit/forgegit/model/git_repo.py
@@ -26,6 +26,7 @@ from collections import namedtuple
 from datetime import datetime
 from glob import glob
 import gzip
+from time import time
 
 import tg
 import git
@@ -495,6 +496,47 @@ class GitImplementation(M.RepositoryImplementation):
         self._repo.default_branch_name = name
         session(self._repo).flush(self._repo)
 
+    def last_commit_ids(self, commit, paths):
+        """
+        Find the ID of the last commit to touch each path.
+        """
+        def prefix_paths_union(a, b):
+            """
+            Given two sets of paths, a and b, find the items from a that
+            are either in b or are parent directories of items in b.
+            """
+            union = a & b
+            prefixes = a - b
+            candidates = b - a
+            for prefix in prefixes:
+                for candidate in candidates:
+                    if candidate.startswith(prefix + '/'):
+                        union.add(prefix)
+                        break
+            return union
+        result = {}
+        paths = set(paths)
+        orig_commit_id = commit_id = commit._id
+        timeout = float(tg.config.get('lcd_timeout', 60))
+        start_time = time()
+        while paths and commit_id:
+            if time() - start_time > timeout:
+                log.error('last_commit_ids timeout for %s on %s', orig_commit_id, ', '.join(paths))
+                return result
+            lines = self._git.git.log(
+                    orig_commit_id, '--', *paths,
+                    pretty='format:%H',
+                    name_only=True,
+                    max_count=1,
+                    no_merges=True).split('\n')
+            commit_id = lines[0]
+            changes = set(lines[1:])
+            changed = prefix_paths_union(paths, changes)
+            for path in changed:
+                result[path] = commit_id
+            paths -= changed
+        return result
+
 class _OpenedGitBlob(object):
     CHUNK_SIZE=4096
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/363e3a2f/ForgeGit/forgegit/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 575ccba..ab2ef8f 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -432,6 +432,20 @@ class TestGitImplementation(unittest.TestCase):
                 Object(name='foo', object_id='1e146e67985dcd71c74de79613719bef7bddca4a'),
             ])
 
+    def test_last_commit_ids(self):
+        repo_dir = pkg_resources.resource_filename(
+            'forgegit', 'tests/data/testrename.git')
+        repo = mock.Mock(full_fs_path=repo_dir)
+        impl = GM.git_repo.GitImplementation(repo)
+        lcd = lambda c, p: impl.last_commit_ids(mock.Mock(_id=c), p)
+        self.assertEqual(lcd('13951944969cf45a701bf90f83647b309815e6d5', ['f2.txt', 'f3.txt']), {
+                'f2.txt': '259c77dd6ee0e6091d11e429b56c44ccbf1e64a3',
+                'f3.txt': '653667b582ef2950c1954a0c7e1e8797b19d778a',
+            })
+        self.assertEqual(lcd('259c77dd6ee0e6091d11e429b56c44ccbf1e64a3', ['f2.txt', 'f3.txt']), {
+                'f2.txt': '259c77dd6ee0e6091d11e429b56c44ccbf1e64a3',
+            })
+
 
 class TestGitCommit(unittest.TestCase):