Return-Path: X-Original-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 98A0B10752 for ; Tue, 22 Oct 2013 21:56:25 +0000 (UTC) Received: (qmail 41014 invoked by uid 500); 22 Oct 2013 21:52:10 -0000 Delivered-To: apmail-incubator-allura-commits-archive@incubator.apache.org Received: (qmail 40618 invoked by uid 500); 22 Oct 2013 21:51:21 -0000 Mailing-List: contact allura-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: allura-dev@incubator.apache.org Delivered-To: mailing list allura-commits@incubator.apache.org Received: (qmail 39827 invoked by uid 99); 22 Oct 2013 21:50:16 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 22 Oct 2013 21:50:16 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 7786F5460A; Tue, 22 Oct 2013 21:50:13 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: johnsca@apache.org To: allura-commits@incubator.apache.org Date: Tue, 22 Oct 2013 21:50:55 -0000 Message-Id: In-Reply-To: <809339d8db6e4b33ad655f9f6d757d71@git.apache.org> References: <809339d8db6e4b33ad655f9f6d757d71@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [45/50] git commit: [#6686] Implement an indexless last_commit_ids for Git [#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 Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/a482b458 Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/a482b458 Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/a482b458 Branch: refs/heads/cj/6422 Commit: a482b45810c1698c9cccd64ff55e4e8e2609a580 Parents: 5ee1e72 Author: Cory Johns Authored: Tue Oct 1 14:52:00 2013 +0000 Committer: Cory Johns Committed: Mon Oct 21 20:31:08 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/a482b458/ForgeGit/forgegit/model/git_repo.py ---------------------------------------------------------------------- diff --git a/ForgeGit/forgegit/model/git_repo.py b/ForgeGit/forgegit/model/git_repo.py index 3efc519..1f2ae37 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 @@ -497,6 +498,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/a482b458/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 a494886..ea615b6 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):