aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Spiers <git@adamspiers.org>2016-05-26 00:28:25 +0100
committerAdam Spiers <git@adamspiers.org>2017-01-02 13:06:39 +0000
commitd601e35f6ea42eb6110e3d1449d03f16a1da3f10 (patch)
tree8f2a9a399435b4c0ed9cc8aabe5d5a850779f39b
parente4fb3d9eb288b3f0ed8cce1e8e58bd805ef3eed0 (diff)
downloadgit-deps-d601e35f6ea42eb6110e3d1449d03f16a1da3f10.tar.gz
allow passing a revision range to CLI or web UI
Now revision ranges like A..B or A...B are also accepted, and then git deps will analyse the dependencies for all revisions in that range. In the CLI invocation, if a dependency is encountered more than once from separate commits, it will only be output once.
-rwxr-xr-xgit-deps.py82
-rw-r--r--html/git-deps.html2
-rw-r--r--html/js/git-deps-data.coffee2
-rw-r--r--html/js/git-deps-graph.coffee13
4 files changed, 71 insertions, 28 deletions
diff --git a/git-deps.py b/git-deps.py
index 568abfa..8c3572e 100755
--- a/git-deps.py
+++ b/git-deps.py
@@ -107,6 +107,19 @@ class CLIDependencyListener(DependencyListener):
too long for useful output if recursion is enabled.
"""
+ def __init__(self, options):
+ super(CLIDependencyListener, self).__init__(options)
+
+ # Count each mention of each revision, so we can avoid duplicating
+ # commits in the output.
+ self._revs = {}
+
+ def new_commit(self, commit):
+ rev = commit.hex
+ if rev not in self._revs:
+ self._revs[rev] = 0
+ self._revs[rev] += 1
+
def new_dependency(self, dependent, dependency, path, line_num):
dependent_sha1 = dependent.hex
dependency_sha1 = dependency.hex
@@ -117,10 +130,10 @@ class CLIDependencyListener(DependencyListener):
else:
print("%s %s" % (dependent_sha1, dependency_sha1))
else:
- if not self.options.log:
+ if not self.options.log and self._revs[dependency_sha1] <= 1:
print(dependency_sha1)
- if self.options.log:
+ if self.options.log and self._revs[dependency_sha1] <= 1:
cmd = [
'git',
'--no-pager',
@@ -281,6 +294,12 @@ class GitUtils(object):
return matching
+ @classmethod
+ def rev_list(cls, rev_range):
+ cmd = ['git', 'rev-list', rev_range]
+ return subprocess.check_output(cmd).strip().split('\n')
+
+
class InvalidCommitish(StandardError):
def __init__(self, commitish):
self.commitish = commitish
@@ -367,6 +386,9 @@ class DependencyDetector(object):
logger.addHandler(handler)
return logger
+ def seen_commit(self, rev):
+ return rev in self.commits
+
def get_commit(self, rev):
if rev in self.commits:
return self.commits[rev]
@@ -670,11 +692,12 @@ def cli(options, args):
detector.add_listener(listener)
- for dependent_rev in args:
- try:
- detector.find_dependencies(dependent_rev)
- except KeyboardInterrupt:
- pass
+ for revspec in args:
+ for rev in GitUtils.rev_list(revspec):
+ try:
+ detector.find_dependencies(rev)
+ except KeyboardInterrupt:
+ pass
if options.json:
print(json.dumps(listener.json(), sort_keys=True, indent=4))
@@ -743,26 +766,43 @@ def serve(options):
client_options['repo_path'] = os.getcwd()
return jsonify(client_options)
- @webserver.route('/deps.json/<commitish>')
- def deps(commitish):
+ @webserver.route('/deps.json/<revspec>')
+ def deps(revspec):
detector = DependencyDetector(options)
listener = JSONDependencyListener(options)
detector.add_listener(listener)
- try:
- root_commit = detector.get_commit(commitish)
- except InvalidCommitish as e:
- return json_error(
- 422, 'Invalid commitish',
- "Could not resolve commitish '%s'" % commitish,
- commitish=commitish)
+ if '..' in revspec:
+ try:
+ revisions = GitUtils.rev_list(revspec)
+ except subprocess.CalledProcessError as e:
+ return json_err(
+ 422, 'Invalid revision range',
+ "Could not resolve revision range '%s'" % revspec,
+ revspec=revspec)
+ else:
+ revisions = [revspec]
+
+ for rev in revisions:
+ try:
+ commit = detector.get_commit(rev)
+ except InvalidCommitish as e:
+ return json_error(
+ 422, 'Invalid revision',
+ "Could not resolve revision '%s'" % rev,
+ rev=rev)
+
+ detector.find_dependencies(rev)
+
+ tip_commit = detector.get_commit(revisions[0])
+ tip_sha1 = tip_commit.hex
- detector.find_dependencies(commitish)
json = listener.json()
- json['root'] = {
- 'commitish': commitish,
- 'sha1': root_commit.hex,
- 'abbrev': GitUtils.abbreviate_sha1(root_commit.hex),
+ json['query'] = {
+ 'revspec': revspec,
+ 'revisions': revisions,
+ 'tip_sha1': tip_sha1,
+ 'tip_abbrev': GitUtils.abbreviate_sha1(tip_sha1),
}
return jsonify(json)
diff --git a/html/git-deps.html b/html/git-deps.html
index 2957e74..848ccad 100644
--- a/html/git-deps.html
+++ b/html/git-deps.html
@@ -26,7 +26,7 @@
</p>
<form class="commitish" action="#">
- Detect dependencies for commit:
+ Detect dependencies for:
<input type="text" name="commitish" size="20"
value="master" autofocus />
<button>Submit</button>
diff --git a/html/js/git-deps-data.coffee b/html/js/git-deps-data.coffee
index 9034b18..34715a3 100644
--- a/html/js/git-deps-data.coffee
+++ b/html/js/git-deps-data.coffee
@@ -82,7 +82,7 @@ add_data = (data) ->
return [
new_nodes
new_deps
- data.root
+ data.query
]
return false
diff --git a/html/js/git-deps-graph.coffee b/html/js/git-deps-graph.coffee
index b2d36fa..299ed0b 100644
--- a/html/js/git-deps-graph.coffee
+++ b/html/js/git-deps-graph.coffee
@@ -356,13 +356,16 @@ launch_viewer = (d) ->
new_data_notification = (new_data) ->
new_nodes = new_data[0]
new_deps = new_data[1]
- root = new_data[2]
+ query = new_data[2]
notification =
- if root.commitish == root.sha1
- "Analysed dependencies of #{root.abbrev}"
+ if query.revspec == query.tip_sha1
+ "Analysed dependencies of #{query.revspec}"
+ else if query.revisions.length == 1
+ "<span class=\"commit-ref\">#{query.revspec}</span>
+ resolved as #{query.tip_abbrev}"
else
- "<span class=\"commit-ref\">#{root.commitish}</span>
- resolved as #{root.sha1}"
+ "<span class=\"commit-ref\">#{query.revspec}</span>
+ expanded; tip is #{query.tip_abbrev}"
notification += "<p>#{new_nodes} new commit"
notification += "s" unless new_nodes == 1
notification += "; #{new_deps} new " +