From b13331e6a6e42a2219890224ff1b170b8f8785ec Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Mon, 18 Dec 2017 12:29:09 +0200 Subject: Add: projgraph --- projgraph | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 projgraph diff --git a/projgraph b/projgraph new file mode 100755 index 0000000..c3f5757 --- /dev/null +++ b/projgraph @@ -0,0 +1,96 @@ +#!/usr/bin/python3 + +import sys + +import yaml + + +unknown = 0 +blocked = 1 +finished = 2 +ready = 3 +next = 4 + +statuses = { + 'blocked': blocked, + 'finished': finished, + 'ready': ready, + 'next': next, +} + +def nodeattrs(done): + attrs = { + unknown: {'shape': 'diamond'}, + blocked: {'color': '#777777', 'shape': 'rectangle'}, + finished: {'color': '#eeeeee'}, + ready: {'color': '#bbbbbb'}, + next: {'color': '#00cc00'}, + } + + a = dict(attrs[done]) + if 'style' not in a: + a['style'] = 'filled' + return ' '.join('{}="{}"'.format(key, a[key]) for key in a) + + +def find_unknown(tasklist): + return [t for t in tasklist if t['status'] == unknown] + + +def all_deps(tasks, task, status): + for dep_name in task.get('depends', []): + dep = tasks[dep_name] + if dep['status'] != status: + return False + return True + + +def any_dep(tasks, task, status): + for dep_name in task.get('depends', []): + dep = tasks[dep_name] + if dep['status'] == status: + return True + return False + + +def set_status(tasks): + tasklist = list(tasks.values()) + for task in tasklist: + if 'status' not in task: + task['status'] = unknown + else: + task['status'] = statuses[task['status']] + unknown_tasks = find_unknown(tasklist) + while unknown_tasks: + for t in unknown_tasks: + if not t.get('depends', []): + t['status'] = ready + else: + if all_deps(tasks, t, finished): + t['status'] = ready + else: + t['status'] = blocked + unknown_tasks = find_unknown(tasklist) + + +obj = yaml.safe_load(sys.stdin) +ikiwiki = sys.argv[1:] == ['ikiwiki'] + +if ikiwiki: + print('[[!graph src="""') +else: + print('digraph "project" {') + +tasks = obj['tasks'] +set_status(tasks) +for name, task in tasks.items(): + print('{} [label="{}"]'.format(name, task['label'])) + status = task['status'] + print('{} [{}]'.format(name, nodeattrs(status))) + for dep in task.get('depends', []): + print('{} -> {}'.format(name, dep)) + +if ikiwiki: + print('"""]]') +else: + print('}') -- cgit v1.2.1