Use topological sort for migration operation dependency resolution

rather than an ad-hoc algorithm
Test case with an infinite loop in graph.dfs