Delphi Programming Observations

Wednesday, March 16, 2011

Delphi, Git and the future

I’m getting more and more hits to this blog for searches including the words “git” and “delphi”, as well as seeing more Delphi people mention git and use GitHub on twitter and stack overflow.

I’m still happy with using the MSysGit bash console to work with git, but it seems more people are finding Git Extensions to provide a good experience right in the Windows shell.

There is a project called libgit2 that was started a while ago, and was renewed during last year’s (2010) Google Summer of Code, and put on GitHub/libgit2. It is a library for dealing with git repositories, and can be linked to other code without requiring the other code to also be GPL, which I think is a big plus. It can be compiled into a DLL with Microsoft Visual C++ Express (available from MS at no cost). The project has had a lot of activity lately, with bindings for several languages.

I started a project called GitForDelphi to create bindings for Delphi. It currently exposes all the functions exported from libgit2, and I translated some of the unit tests from the libgit2 project. I tried to get all the tests that confirm the functionality rather than internal details, and all the tests that I translated to Delphi are currently passing.

As I said, the libgit2 project is very active, and so far I’ve only been tracking the exported C API. I don’t think this is ideal for Delphi users, especially when you come across things like structures with pointers to pointers. These are easy to deal with in C with array indexing, but it gets a little hairy in Delphi. I intend to hide a lot of the C API in a wrapper class, but I haven’t figured out just how I want it to look yet; I’ll probably name it TGitRepository.

If you’d like to contribute, I’m on twitter as @jasonpenny, or fork the repo on GitHub.

An example of hairy Delphi translation of C code:

entries = (git_index_entry **)index->entries.contents;

for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {
	git_index_entry *e = entries[TEST_ENTRIES[i].index];

	must_be_true(strcmp(e->path, TEST_ENTRIES[i].path) == 0);
	must_be_true(e->mtime.seconds == TEST_ENTRIES[i].mtime);
	must_be_true(e->file_size == TEST_ENTRIES[i].file_size);
entries := PPgit_index_entry(index.entries.contents);

for i := Low(TEST_ENTRIES) to High(TEST_ENTRIES) do
   // this took me a while to get right
   offset := TEST_ENTRIES[i].index * sizeof(Pgit_index_entry);
   e := PPgit_index_entry(Integer(entries) + offset)^;

   CheckTrue(StrComp(e.path, TEST_ENTRIES[i].path) = 0);
   CheckTrue(e.mtime.seconds = TEST_ENTRIES[i].mtime);
   CheckTrue(e.file_size = TEST_ENTRIES[i].file_size);
posted by Jason at 8:39 pm  

2 Responses to “Delphi, Git and the future”

  1. M.C. Botha says:


    Thank you for GitForDelphi.
    I would like to contribute to TGitRepository, would it be possible to furnish me with an outline in order to help with the development?

    Kind regards

    • Jason says:

      I don’t really have an outline, I planned to start very simple and just add features over time, so to start with I figure it should be able to do these simple things: create/open a repository, create commits, get the history with the revwalker; those should all be possible with libgit2 today. Two more simple things that I’d like to see which are not yet in libgit2 are `git status` and `git checkout` (although there is support for extracting a single file with the blob functions).

      I’ll see what I can come up with over the next few weeks