The Slog A development blog by Liam Siira

The Difficulty With Codegit

- Posted in atheos

I recently decided to start integrating the Codegit plugin directly into Atheos. It's simply too valuable to the everyday developer to not be a core feature. Now I have been actively avoiding working on Codegit because whenever I opened its code up, I'd instantly feel a bit overwhelmed. The idea of building a git interface was a massive undertaking that I would pass up 10/10 times. Codegit was simply over my head and looking at its code made that clear. Eventually I worked myself up to start working on it. Good times were not had. For lack of a polite way to say it, Codegit is probably the worst code I've come across in Atheos. It's still an amazing plugin, and the original developer had to make it without being able to see the end goal, from scratch. 90% of the code behind Codegit is rock solid amazing code, but the overall structure is insanely over complicated.

Let's take a look at some pseudo code for implementing a simple Commit. Now keep in mind, Atheos is a client-server software and everything takes place as a series of request/replies from one to the other. From the perspective of the client software, committing a change using git could be thought of as:

 01. Client->Server: Request the Codegit overview window.
 02. Server->GitCLI: Request an updated repo status and build a table full of files.
 03. Server->Client: Send the HTML for the Codegit overview.
 04. Client->Server: Request the Staging/Diff window for files to be committed.
 05. Server->GitCLI: Request the repo status & determine each files status.
 06. Server->GitCLI: Request the diff for that file, or if untracked, count the lines as additions.
 07. Server->Client: Return the rendered HTML for the Staging/Diff window of the requested files.
 04. Client->Server: Send the commit message and the files you want committed.
 05. Server->Git CLI: Server stages the files or sends an error if it can't.
 06. Server->Git CLI: Server commits the files or sends an error if it can't.
 07. Server->Client: Sends a success message.
 08. Client: Removes commit files from overview table.

Now let's take a look at how CodeGit originally achieved the goal.

 01. Client->Server: Request the Codegit overview window.
 02. Server->Client: Send the empty html for the Codegit overview.
 03. Client->Server: Request the current repo status.
 04. Server->GitCLI: Request the current repo status.
 05. Server->Client: Send the parsed repo status.
 06. Client: Process the repo data and render the overview table.
 07. Client: Cache the selected files to internal memory.
 08. Client->Server: Request the staging/diff window.
 09. Server->Client: Send the empty html for the staging/diff window.
 10. Client>>Server: Request the diff info for the cached files individually. Yes. For every file, a seperate request is made.
    01. Server->GitCLI: Request the repo status, and determine the status of that file.
    02. Server->GitCLI: Request the diff for that file, or if untracked, count the lines and return each as an addition.
    03. Server->Client: Return the semi-parsed data.
    04. Client: Process the raw diff into html and append to the diff view.
 11. Client->Server: Send the request to add the files to the staging area.
 12. Server->GitCLI: Server stages the files or sends an error if it can't.
 13. Client->Server: Send the commit message and request to commit the files.
 14. Server->GitCLI: Server commits the files or sends an error if it can't.
 15. Server->Client: Sends a success message.
 16. Client->Server: Request the Codegit overview window.
 17. Server->Client: Send the empty html for the Codegit overview.
 18. Client->Server: Request the current repo status.
 19. Server->GitCLI: Request the current repo status.
 20. Server->Client: Send the parsed repo status.
 21. Client: Process the repo data and render the overview table.

Again, I am able to see the end goal clearly as soon as I started working on Codegit, which is an insane advantage that the OG dev did not have. From that perspective, anyone would be asking "How did he manage to get THAT to work?", but I can't honestly say that I wouldn't have made something similar had I been building it from scratch.

For one, I prefer Javascript over PHP. I've gotten much more comfortable with PHP due to working so heavily on Atheos, but that's not everyone, and so trying to have as much as possible in JS would be very appealing, and could explain a lot of the decisions behind sending so many requests to the Server to be rendered/parsed on the Client.

When building something from scratch, I tend not to create a detailed plan when I'm coding for two main reasons:

  1. A detailed-enough pseudo code plan is only one or two steps away from just coding the darn thing, and a simple overview idea doesn't help avoid the pitfalls enough for it to be worthwhile to me.

  2. I am not a computer; coding to me is mostly pseudo code until I put it in action, and as such, things I think are or should be possible sometimes aren't. Git doesn't seem to easily show the differential for an untracked file. Atheos handles most everything as either an Array or an Object, and in Javascript, it's very clear which one you're working with. In PHP, it's a little less clear, only a tiny bit, but due to the weird way Atheos handles Server-Client communication, sending an OBJ to the server can sometimes be a PHP Obj, or an Array. I know it's consistent, and I'm close to figuring out why that happens and how to fix it, but it can cause a huge headache when trying to handle the requests.

If you don't have a detailed plan, the original CodeGit makes sense. You'd build each function as you realize you need it, and that's exactly what I think happened. The OG Dev needed to get from A to Z, and started building each step only as they were needed and subsequently made an overly complicated system, especially keeping in mind that every function made was probably designed to be as generic as possible just in case they needed to be used elsewhere. Hindsight being 2020 tells me that many of those functions became way too generic and as such were heavily non-performant; in some cases nigh useless.

I think the main and only real fault with CODEVI is that once it was completed, nobody went back through and streamlined/optimized at all. I was able to rebuild the commit system in a single day and most of it was due to not knowing enough about Code git itself. As my familiarity with it has grown, rewriting major components has become fairly trivial.

Back to List