Replies: 1 comment 5 replies
-
Thanks so much for the writeup and for implementing a git-style blame!
I agree, and think having a tested and working version first would pave the way for further integration, however that will be done then. Tests
With Understanding
This seems to be a complex algoriithm, but maybe it can use the commitgraph if present just like Next steps?Yes, a PR would be great for sure. My way of doing things will be to get hands-on very fast, maybe in an attempt to integrate it, and that can happen as soon as there are some tests. So maybe that PR would start out as code-dump, from there tests can be ported, and then one can see how the real topo-sort would integrate into Thanks again, a great read of an awesome feature! (I wasn't even aware the current topo-sort isn't the real one, so I guess I don't understand it either 😅.) |
Beta Was this translation helpful? Give feedback.
-
Background
TL;DR: Wanted to reimplement own Git script as a Rust program with
gitoxide
but need proper topological sorting.I use this script a lot in my workflow. On Windows with MSYS2 it's very slow. I wanted to learn more Rust (which by now I feel I can say I know) and also found
gitoxide
. Match made in heaven. So I set about implementing agit_blame
. (Yes, before The Big Rename... When I startedgitoxide
didn't have integrated diffing... 😄)Things happened in life. Next time I picked it up
gitoxide
was very different, so I could get started right on the blame path.Then other things happened in life... Eventually I managed to write a very crude
blame
implementation that works surprisingly well for what it is. But after a while I hit a road block, and eventually figured out that the reason was that the revisions I got back fromAncestors
appear in a different order. So I switched gears and startedwritingblatantly copying topological sorting from Git.As noted several places (and just above) the current
Ancestors
does not do the exact same thing as Git itself does. Implementing git-like topological sorting would benefitgitoxide
, making it easier to implement finding merge bases and enable several proposed oxidized utilities.Implementation
My implementation is very much based on the existing Git implementation introduced in b45424181e as well as improvements done since then. Function names are kept as much as possible (even though I don't always agree with them). In short it is a three stage process that aims to reduce the amount of traversal needed before the first result can be output.
The implementation is currently developed on as a separate crate. I tried several times to integrate this sorting into the current
Ancestors
as a separate sorting type but failed. It was easier to get started with a clean slate. Given the amount of state the topological walk keeps it is perhaps best to keep it separate from the existing traversal (?).My current goal is to make
topo.rs
a module next togix_traverse::commit
. For testing purposes I have "merged" my code into gitoxide to be able to easier align types and general style. (Again, only for testing purposes, I literally made a symlink fromgitoxide
to mytopo.rs
to not have to update code two places. You can see it here). It compiles just fine :) But that is why my code has some weird feature gates in it.Issues
This is not PR-ready. Several issues need to be ironed out. Here are a few of them:
Tests
My own repo has a bunch of tests that compare my walk to the output of
git rev-parse
. However, I have literally embedded a separate commit history into my repo (which admittedly works quite well). EnhancingTraversalAssertion
(or making a similar thing) would be needed.Abstraction level
I feel my implementation (bugs/issues notwithstanding) sort of falls in between
gix_traverse::commit::Ancestors
andgix::revision::Walk
. It would be nice to split it in two like the existing walk, but I don't know exactly where to draw the line. Currentlygix_traverse
adds a dependency ongix-revision
, which can easily be avoided. Also, regardless of where and whether to split, there is currently no way to access this code fromgix
directly. But it compiles!BTW I have started writing some docs, but they aren't hosted anywhere at the moment.
Understanding
I cannot honestly say I fully understand how it works... I emailed the original author with some questions, but haven't been graced with a reply. It's been a couple of months by now, so I doubt I will ever receive one. But I learned a lot by thoroughly reading the email thread in which it was first added to git and relevant commit messages.
One interesting thing is that Git refuses to use this algorithm unless it has at least some generation numbers available. If it doesn't then it falls back to the old method of walking the entire history and then calculating indegrees backwards (which is also what libgit2 does). But my implementation works without any generation numbers at all, and I believe Git's own does too (I recall recompiling Git to get rid of the restriction and test this). Though I can't prove it what I think happens is that in absence of generation numbers the first walk ("explore") degenerates into a full walk making it essentially the same as the other implementation.
Next steps?
Development has stagnated a bit before and during the holidays. I need a fresh perspective on things... First off: does this seem like a decent foundation to build on to get topological sorting into
gitoxide
? If so, would it make sense to make a PR just to make it easier to discuss the particulars of the code?Beta Was this translation helpful? Give feedback.
All reactions