Using Libgit-CLI as an alternative to Libgit2 FFI in Iceberg

GToolkit uses git to manage external source code. The library/framework that makes this possible is called Iceberg. In its normal implementation, Iceberg uses libgit2 as an FFI library to do git operations.

Libgit-CLI (inside Iceberg-Git-CLI) is an alternative implementation that uses external process invocations of the git executable to do git operations.

Though not yet completely finished, the implementation works well enough so that it can be ued by a wider audience for day to day work.

This page describes how to get started.

Prerequisites

Libgit-CLI uses a git executable on your system. At the moment this executable should first be installed and configured on your system. In particular SSH key usage should be set up so that you are able to clone, pull and push on the command line.

GToolkit will expect the git executable to be reachable from the system's PATH. Make sure to start GToolkit so that this is the case.

macOS

On macOS you can install git through the standard development tools (XCode and friends).

Linux

On Linux git can be installed using the normal package manager, on Ubuntu that would be apt. Though this is easy enough to do, we need a relatively recent version of git. For example, the standard version on Ubuntu 22.04 LTS, 2.34.1, is too old. The current required minimum version is 2.36. You can install a more recent version manually.

sudo add-apt-repository ppa:git-core/ppa

sudo apt install git

Windows

Install following https://gitforwindows.org (even x86 on ARM). Make sure to select the install option Git from command line in the step/page Adjusting your PATH environment.

Authorization/Authentication

For key management, use ssh-agent and ssh-add, one guide is Using SSH agent forwarding.

Add keys to ~/.ssh

On Windows, add/edit ~/.ssh/config

Host github.com HostName github.com IdentityFile ~/.ssh/your-key-name AddKeysToAgent yes

On Windows you might need to start ssh-agent from an Admin PowerShell first or the first time.

Get-Service -Name ssh-agent | Set-Service -StartupType Manual

Start-Service ssh-agent

Then add key using ssh-add your-key-name from a normal command shell. Check with ssh-add -l then test access with ssh -T git@github.com

On Windows, make git use the system ssh, not its own ssh.

git config --global core.sshCommand 'C:/Windows/System32/OpenSSH/ssh.exe'

Now test clone, pull and push operations on the command line! Furthermore these operations should run unattended. I.e. they should not ask for passwords, apart from initial setup.

Platform

The class IceGitCliPlatform Object subclass: #IceGitCliPlatform instanceVariableNames: 'gitExecutable signalClass signCommits gitExecutableName' classVariableNames: 'current' package: 'Iceberg-Git-CLI-Support' defines the environment for Libgit-CLI to operate on. Inspect its current instance to get more details.

IceGitCliPlatform current
  

If you followed the instructions in the previous sections, you should see good values here. The validate button runs a number of asserts with descriptions of failures.

You can set the path to the git executable if needed.

There is also a view to look at the git config settings. Note that user.name and user.email need to be set.

Testing Libgit-CLI usage on specific repositories

The utility class GtIceRepositorySwitcher Object subclass: #GtIceRepositorySwitcher instanceVariableNames: 'icebergLocation sshUrl iceRepository creator' classVariableNames: '' package: 'Iceberg-Git-CLI-Support' can be used to test the LIbgit-CLI implementations on specific repositories, registered with the system or not. There are multiple options to create test instances. You can also switch existing repositories, toggling them between the 2 implementations.

Working with registered repositories makes them usuable through the standard GToolkit git UI tool. These will automatically be notified of code changes. Unregistered repository can be used via views and actions on GtGitRepository Object subclass: #GtGitRepository uses: TGtAnnouncer instanceVariableNames: 'icebergRepository announcer lepiterWorkingCopy status viewModel' classVariableNames: '' package: 'GToolkit4Git-Model' (called tool further down).

The following expression will clone the gt4git repository in a temporary directory using the new implementation and open tool on it. Note that we did not call register so the system registry is not modified.

GtIceRepositorySwitcher new
	sshUrl: 'git@github.com:feenkcom/gt4git.git';
	useLibgitCLI;
	useTemp;
	deleteDirectory;
	cloneAndCreate;
	tool
  

You can also load an existing on disk repository.

GtIceRepositorySwitcher new
	sshUrl: 'git@github.com:feenkcom/gt4git.git';
	useLibgitCLI;
	useTemp;
	loadAndCreate;
	tool
  

Other options are GtIceRepositorySwitcher>>#useLibgit2 useLibgit2 "Set our repository creator to use the Iceberg Libgit2 FFI library" creator := IceRepositoryCreator and GtIceRepositorySwitcher>>#useSystem useSystem "Switch to the main system iceberg location. This is a default" self icebergLocation: nil as well as GtIceRepositorySwitcher>>#register register "Register the created repository with the system. The logic here allows switching, replacing an existing repository" | index | self iceRepository ifNil: [ self error: 'Repository not yet created, use #loadAndCreate, #cloneAndCreate or #named:' ]. index := IceRepository registry findFirst: [ :each | each name = self projectName ]. index isZero ifTrue: [ self iceRepository register ] ifFalse: [ IceRepository registry at: index put: self iceRepository. Iceberg announcer announce: (IceRepositoryCreated repository: self iceRepository). ]

Switching an existing, registered and functional repository is very easy.

GtIceRepositorySwitcher new switch: 'gt4git'
  

The tool UI (also available by clicking the i icon on top of the git tool) allows for a look inside. You can use GtIceRepositorySwitcher>>#named: named: aRepositoryName "Initialize from the registered Iceberg repository named aRepositoryName" iceRepository := self lookup: aRepositoryName. self sshUrl: iceRepository originUrl. self icebergLocation: iceRepository location parent parent to access a registered repository.

GtIceRepositorySwitcher new named: 'gt4git'; tool
  

The Details view indicates the currently used implementation, while the hamburger action menu allows you to inspect Logged signals and Grouped events that show the underlying operations recently executed (but limited to the last 64/32 signals/events by default).

Enabling Libgit-CLI usage for new repositories

To enable Libgit-CLI usage for all newly created repositories (either through the GT Git tool UI or through Metacello code loading), you have to install the platform with the following expression.

IceGitCliPlatform current install
  

There is also an uninstall option should you need it. There are action buttons on the current instance to install and uninstall.

Switching all system repositories to Libgit-CLI usage

The option to switch all repositories over to the new implementation is actually independent of the functionality of the switcher itself.

GtIceRepositorySwitcher switchAll
  

The option to switch bac us called revert all.

GtIceRepositorySwitcher revertAll