A long time ago I started hacking on a library I named libQtGit. As you’ll deduce from the name, it provides a Qt-like API to git, the stupid content tracker.
I had a vision for libQtGit: it was not an end in itself but a piece of a more ambitious framework/library tentatively named QVersioned or libQtVersioned.
QVersioned would provide QVersionedDir and QVersionedFile classes (amongst others, but those two are the most important). Those classes would essentially have the same API QDir and QFile have. QVersioned would open ZIP files and store a .git directory inside. There are cases, like ODF (which itself is a ZIP file) where nothing special is needed. For other cases (for instance, a .txt file), there would be a .txtv (meaning “.txt versioned”) which would be a ZIP file containing the .txt + .git directory (why ZIP? because it’s supported natively by Windows XP and newer and Mac OS).
Now, how did I intend to implement ODF versioning, which was going to be the “this thing works” case?:
- The .git folder would store the uncompressed contents of the ODF file, i. e. XML, images, etc. This is needed to avoid duplication, allow diffs, etc
- There would be also a full copy of the latest version (XML, images, etc) in the ZIP file, just like any ODF-capable application not supporting QVersioned would expect (these applications would just ignore the .git directory)
- When a QVersioned-capable application opens an ODF file, it compares the XML, images, etc to the latest version in git:
- If the diff is empty, last save was by a QVersioned-capable application, no action needed at moment
- If the diff is not empty, last save was by a QVersioned-incapable application. A new “git commit -a” is performed. Yes, we probably have lost “versions” of the document in between this commit and the former one but something’s better than nothing.
By using libQtGit and QVersioned, it would also be possible to add collaboration features such as “send me an update” (i. e. send me a diff which transforms my outdated document into your latest version), collaborative editing (send diffs back and forth) and more things I cannot think of right now.
In case you are interested in the libQtGit API (remember QVersioned will offer a higher-level API), this is the signature of the method you would call:
Git::Repository::Commit* Git::Repository::commit ( const
QString& message = QString(),
const Commit* c = 0,
const QString& author = QString(),
const CommitFlags cf = DefaultCommitFlags,
const CleanUpMode cum = DefaultCleanUpBehavior );
That’s equivalent to “git commit -C commit_id -m “message” “.
CommitFlags is a QFlag and CleanUpMode a QEnum:
enum CommitFlag {
DefaultCommitFlags = 0x0 /*< git commit */,
OverrideIndexCommit = 0x1 /*< git commit -a */,
SignOffCommit = 0x2 /*< git commit -s */,
AmendCommit = 0x4 /*< git commit --amend */,
AllowEmptyCommit = 0x8 /*< git commit --allow-empty */,
NoVerifyCommit = 0x16 /*< git commit -n */
};
Q_DECLARE_FLAGS ( CommitFlags, CommitFlag )
enum CleanUpMode {
DefaultCleanUpBehavior = 0x0 /*< git commit */,
VerbatimClean = 0x1 /*< git commit --cleanup=verbatim */,
WhiteSpaceClean = 0x2 /*< git commit --cleanup=whitespace*/,
StripClean = 0x4 /*< git commit --cleanup=strip */,
DefaultClean = 0x8 /*< git commit --cleanup=default */
};
Q_ENUMS ( CleanUpMode )
For the "git commit -a -m "Save latest unversioned version on ODF document opening" ", we would use:
// Assuming 'repo' is a valid Git::Repository object
repo->commit ( "Save latest unversioned version on ODF document opening",
0,
"(The application would probably take the
author's name from the product registration)",
Git::Repository::OverrideIndexCommit );
So, how is libQtGit doing? Well, the API is there for git add, commit, init, mv, rm, checkout, clone, branch, revert, reset, clean, gc, status, merge, push, fetch, pull, rebase, config, update-server-info and (partially) symbolic-ref.
When I say “the API is there” I mean “all the QFlags, QEnums, methods, classes and its translation to git parameters is done”. It’s just a matter of implementing the QProcess part, parsing output, etc. Boring and
time-consuming but easy.
Given that I’m busy with other stuff, and some people have been asking for the code for a long time (sorry Riccardo!), I have just published what I have now. It’s unfinished, barely tested and yet to implement in many places. But it’s a starting point. It’s available now from Gitorious: http://gitorious.org/libqtgit/libqtgit
As for QVersioned, nothing is done yet.