From ee5eeea541f072b908947ffca5799cda55701db6 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 3 Sep 2017 20:11:31 -0700 Subject: [PATCH] Show branch tips --- dvc/git_wrapper.py | 24 +++++++++++++++++++++--- dvc/graph/commit.py | 24 ++++++++++++++++++++---- dvc/graph/workflow.py | 12 +++++++++--- tests/test_workflow.py | 7 +++++-- 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/dvc/git_wrapper.py b/dvc/git_wrapper.py index ff9aae3f5..a5501b990 100644 --- a/dvc/git_wrapper.py +++ b/dvc/git_wrapper.py @@ -1,4 +1,6 @@ import os +import re +from collections import defaultdict from dvc.logger import Logger from dvc.config import Config @@ -243,14 +245,18 @@ class GitWrapper(GitWrapperI): '--pretty=format:{}'.format(format_str)] lines = Executor.exec_cmd_only_success(git_cmd).split('\n') - wf = Workflow(target, merges_map) + branches_multimap = GitWrapper.branches_multimap() + + wf = Workflow(target, merges_map, branches_multimap) for line in lines: items = line.split(GitWrapper.LOG_SEPARATOR, len(GitWrapper.LOG_FORMAT)) assert len(items) == 5, 'Git wrapper: git log format has {} items, 5 expected'.format(len(items)) hash, parent_hash, name, date, comment = items - wf.add_commit(Commit(hash, parent_hash, name, date, comment, - *self.is_target(hash, target, settings))) + commit = Commit(hash, parent_hash, name, date, comment, + *self.is_target(hash, target, settings), + branch_tips=branches_multimap.get(hash)) + wf.add_commit(commit) return wf except ExecutorError: @@ -322,3 +328,15 @@ class GitWrapper(GitWrapperI): # lines = map(str.strip, Executor.exec_cmd_only_success(git_cmd).split('\n')) # lines.map return {} + + @staticmethod + def branches_multimap(): + git_cmd = ['git', 'show-ref', '--abbrev={}'.format(GitWrapper.COMMIT_LEN)] + lines = Executor.exec_cmd_only_success(git_cmd).split('\n') + items_full = map(unicode.split, lines) + items = map(lambda it: (it[0], re.sub(r'^refs/heads/', '', it[1])), items_full) + + result = defaultdict(list) + for (hash, branch) in items: + result[hash].append(branch) + return result diff --git a/dvc/graph/commit.py b/dvc/graph/commit.py index 736c2da1e..1a3b85bc6 100644 --- a/dvc/graph/commit.py +++ b/dvc/graph/commit.py @@ -3,7 +3,10 @@ class Commit(object): DVC_REPRO_PREFIX = 'DVC repro' COLLAPSED_TEXT = DVC_REPRO_PREFIX + '\n<< collapsed commits >>' - def __init__(self, hash, parents, name, date, comment, is_target=False, target_metric=None): + def __init__(self, hash, parents, name, date, comment, + is_target=False, + target_metric=None, + branch_tips=None): self._hash = hash self._parent_hashes = set(parents.split()) self._name = name @@ -11,6 +14,7 @@ class Commit(object): self._comment = comment self._is_target = is_target self._target_metric = target_metric + self._branch_tips = [] if branch_tips is None else branch_tips self._is_collapsed = False @@ -30,14 +34,18 @@ class Commit(object): @property def text(self): + branch_text = '' + if self._branch_tips: + branch_text = 'Branch tips: {}\n'.format(', '.join(self._branch_tips)) + metric_text = '' if self._is_target and self._target_metric: metric_text = '\nTarget metric: {}'.format(self._target_metric) if self._is_collapsed: - return self.COLLAPSED_TEXT + metric_text + return branch_text + self.COLLAPSED_TEXT + metric_text - return self._comment[:self.TEXT_LIMIT] + '\n' + self.hash + metric_text + return branch_text + self._comment[:self.TEXT_LIMIT] + '\n' + self.hash + metric_text @property def is_repro(self): @@ -56,4 +64,12 @@ class Commit(object): def set_target_metric(self, value): self._target_metric = value - self._is_target = True \ No newline at end of file + self._is_target = True + + @property + def branch_tips(self): + return self._branch_tips + + def add_branch_typs(self, tips): + for tip in tips: + self._branch_tips.append(tip) diff --git a/dvc/graph/workflow.py b/dvc/graph/workflow.py index 4b3db0170..ead5e19a7 100644 --- a/dvc/graph/workflow.py +++ b/dvc/graph/workflow.py @@ -9,9 +9,10 @@ class WorkflowError(DvcException): class Workflow(object): - def __init__(self, target, merges_map, root='', no_repro_commits=True): + def __init__(self, target, merges_map, branches_map=None, root='', no_repro_commits=True): self._target = target self._merges_map = merges_map + self._branches_map = branches_map self._commits = {} self._root = root @@ -91,7 +92,7 @@ class Workflow(object): child_commit_hashes = self._edges.get(commit.hash) if child_commit_hashes and all(self._commits[hash].is_repro for hash in child_commit_hashes): - self._upstream_target_metric(child_commit_hashes, commit) + self._upstream_metric(child_commit_hashes, commit) for hash in child_commit_hashes: self._commits[hash].add_parents(commit.parent_hashes) @@ -106,12 +107,17 @@ class Workflow(object): return False pass - def _upstream_target_metric(self, child_commit_hashes, commit): + def _upstream_metric(self, child_commit_hashes, commit): if commit.has_target_metric: for hash in child_commit_hashes: if not self._commits[hash].has_target_metric: self._commits[hash].set_target_metric(commit.target_metric) + if commit.branch_tips: + for hash in child_commit_hashes: + self._commits[hash].add_branch_typs(commit.branch_tips) + pass + @staticmethod def _redirect_edges(edges, child_commit_hashes, hash, commit_hashes): for h in commit_hashes: diff --git a/tests/test_workflow.py b/tests/test_workflow.py index 8912a4692..e497a9f3f 100644 --- a/tests/test_workflow.py +++ b/tests/test_workflow.py @@ -66,9 +66,11 @@ class TestWorkflow(TestCase): self.assertTrue('2' not in wf._commits) pass - def collapse_target_metric_commit_test(self): + def collapse_metric_commit_test(self): value = 0.812345 - metric_commit3 = Commit('2', '1', 'name1', 'today', 'DVC repro-run ...', True, value) + branches = ['master', 'try_smth'] + metric_commit3 = Commit('2', '1', 'name1', 'today', 'DVC repro-run ...', + True, value, branch_tips=branches) wf = Workflow('', '') wf.add_commit(self._commit1) @@ -80,4 +82,5 @@ class TestWorkflow(TestCase): self.assertEqual(len(wf._commits), 2) self.assertEqual(wf._commits['3']._target_metric, value) + self.assertEqual(wf._commits['3'].branch_tips, branches) pass \ No newline at end of file