aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Spiers <git@adamspiers.org>2013-11-16 20:00:40 -0500
committerAdam Spiers <git@adamspiers.org>2015-01-05 16:57:08 +0000
commit4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 (patch)
treead6f9fbbae4a9a5518903a7e70ce9a4f5d70599e
parent416f4bd63c5b01c1ee105f7dcec20dbff94cedd2 (diff)
downloadgit-deps-4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2.tar.gz
add --exclude-commits
-rwxr-xr-xgit-deps45
1 files changed, 42 insertions, 3 deletions
diff --git a/git-deps b/git-deps
index ec74dc7..81f75c9 100755
--- a/git-deps
+++ b/git-deps
@@ -116,6 +116,9 @@ class DependencyDetector(object):
# A cache mapping SHAs to commit objects
self.commits = {}
+ # Memoization for branch_contains()
+ self.branch_contains_cache = {}
+
# Callbacks to be invoked when a new dependency has been
# discovered.
self.listeners = []
@@ -225,7 +228,15 @@ class DependencyDetector(object):
if not m:
continue
dependency_sha, orig_line_num, line_num = m.group(1, 2, 3)
+ line_num = int(line_num)
dependency = self.get_commit(dependency_sha)
+ line_to_culprit[line_num] = dependency.hex
+
+ if self.is_excluded(dependency):
+ self.logger.debug(' Excluding dependency %s via line %s (%s)' %
+ (dependency_sha[:8], line_num,
+ self.oneline(dependency)))
+ continue
if dependency_sha not in self.dependencies[dependent_sha]:
self.logger.debug(' New dependency %s via line %s (%s)' %
@@ -245,7 +256,6 @@ class DependencyDetector(object):
(line_num, dependent.hex[:8], path))
self.dependencies[dependent_sha][dependency_sha][path][line_num] = True
self.notify_listeners('new_line', dependent, dependency, path, line_num)
- line_to_culprit[int(line_num)] = dependency.hex
diff_format = ' |%8.8s %5s %s%s'
hunk_header = '@@ %s %s @@' % (line_range_before, line_range_after)
@@ -263,6 +273,32 @@ class DependencyDetector(object):
def oneline(self, commit):
return commit.message.split('\n', 1)[0]
+ def is_excluded(self, commit):
+ for exclude in self.options.exclude_commits:
+ if self.branch_contains(commit, exclude):
+ return True
+ return False
+
+ def branch_contains(self, commit, branch):
+ self.logger.debug(" Does %s contain %s?" % (branch, commit.hex[:8]))
+ branch_commit = self.get_commit(branch)
+
+ if commit.hex not in self.branch_contains_cache:
+ self.branch_contains_cache[commit.hex] = {}
+ if branch_commit.hex in self.branch_contains_cache[commit.hex]:
+ memoized = self.branch_contains_cache[commit.hex][branch_commit.hex]
+ self.logger.debug(" %s (memoized)" % memoized)
+ return memoized
+
+ cmd = [ 'git', 'merge-base', commit.hex, branch_commit.hex ]
+ #self.logger.debug(" ".join(cmd))
+ out = subprocess.check_output(cmd).strip()
+ #self.logger.debug(out)
+ result = out == commit.hex
+ self.logger.debug(" %s" % result)
+ self.branch_contains_cache[commit.hex][branch_commit.hex] = result
+ return result
+
def tree_lookup(self, target_path, commit):
"""Navigate to the tree or blob object pointed to by the given target
path for the given commit. This is necessary because each git
@@ -304,10 +340,13 @@ def parse_args():
description='Auto-detect inter-commit dependencies.',
usage='%(prog)s [options] COMMIT-ISH [COMMIT-ISH...]'
)
- parser.add_argument('-r', '--recurse', dest='recurse', action='store_true',
- help='Follow dependencies recursively')
parser.add_argument('-l', '--log', dest='log', action='store_true',
help='Show commit logs for calculated dependencies')
+ parser.add_argument('-r', '--recurse', dest='recurse', action='store_true',
+ help='Follow dependencies recursively')
+ parser.add_argument('-e', '--exclude-commits', dest='exclude_commits',
+ action='append', metavar='COMMITISH',
+ help='Exclude commits which are ancestors of the given COMMITISH')
parser.add_argument('-c', '--context-lines', dest='context_lines', type=int,
metavar='NUM', default=1,
help='Number of lines of diff context to use')