diff --git a/dvc/command/pipeline.py b/dvc/command/pipeline.py index c30160fb9..de0c1ecd3 100644 --- a/dvc/command/pipeline.py +++ b/dvc/command/pipeline.py @@ -14,7 +14,7 @@ logger = logging.getLogger(__name__) class CmdPipelineShow(CmdBase): - def _show(self, target, commands, outs): + def _show(self, target, commands, outs, locked): import networkx from dvc.stage import Stage @@ -22,8 +22,12 @@ class CmdPipelineShow(CmdBase): G = self.repo.graph()[0] stages = networkx.get_node_attributes(G, "stage") node = os.path.relpath(stage.path, self.repo.root_dir) + nodes = networkx.dfs_postorder_nodes(G, node) - for n in networkx.dfs_postorder_nodes(G, node): + if locked: + nodes = [n for n in nodes if stages[n].locked] + + for n in nodes: if commands: logger.info(stages[n].cmd) elif outs: @@ -122,7 +126,7 @@ class CmdPipelineShow(CmdBase): simple_g.add_edges_from(edges) write_dot(simple_g, filename) - def run(self, unlock=False): + def run(self): if not self.args.targets: self.args.targets = self.default_targets @@ -144,7 +148,12 @@ class CmdPipelineShow(CmdBase): target, self.args.commands, self.args.outs ) else: - self._show(target, self.args.commands, self.args.outs) + self._show( + target, + self.args.commands, + self.args.outs, + self.args.locked, + ) except DvcException: msg = "failed to show pipeline for '{}'".format(target) logger.exception(msg) @@ -208,6 +217,13 @@ def add_parser(subparsers, parent_parser): default=False, help="Print output files instead of paths to DVC files.", ) + pipeline_show_parser.add_argument( + "-l", + "--locked", + action="store_true", + default=False, + help="Print locked DVC stages", + ) pipeline_show_parser.add_argument( "--ascii", action="store_true", diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 0bb531454..2e24bb85f 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -1,3 +1,5 @@ +import logging + from dvc.main import main from tests.basic_env import TestDvc @@ -150,6 +152,19 @@ class TestPipelineShow(TestRepro): ret = main(["pipeline", "show", "non-existing"]) self.assertNotEqual(ret, 0) + def test_print_locked_stages(self): + self.dvc.add("foo") + self.dvc.add("bar") + self.dvc.lock_stage("foo.dvc") + + self._caplog.clear() + with self._caplog.at_level(logging.INFO, logger="dvc"): + ret = main(["pipeline", "show", "foo.dvc", "--locked"]) + self.assertEqual(ret, 0) + + assert "foo.dvc" in self._caplog.text + assert "bar.dvc" not in self._caplog.text + class TestPipelineShowDeep(TestReproChangedDeepData): def setUp(self):