When using the git CLI, you can temporarily override / add config values with -c <name>=<value> (and also --config-env=<name>=<envvar>, but that's just a wrapper around -c to keep secret values off the command line). The important key to -c is that it doesn't persist to a file—the config value lives only so long as that process executes, and then it goes away. Pygit2 has no such support for temporary overrides like this—any changes to a Config persist to disk.
libgit2 can support this using config backends. Currently, libgit2 comes with two kinds of config backends—file backends (the standard type) and a read-only in-memory backend constructed from strings. We could, in theory, use the read-only in-memory backend, but its use wouldn't be very Pythonic, and also it's not until the unreleased libgit 1.9.5 that it's possible to construct this backend from the public API (prior to 1.9.5, it was private).
But libgit2's public API supports implementing and attaching any arbitrary custom backend, and it's fairly straightforward (if not verbose) to implement a mutable in-memory backend with CFFI + Python.
As an aside, pygit2 is also lacking a wrapper around git_config_open_default, which is relevant to the approach I'm taking.
With the pull request I'm posting shortly, Config (without any public API breakage) becomes a fully-functional base class that, on its own, does what it has always done: wraps access to configuration files. Two new classes DefaultConfig and RepositoryConfig now extend Config: the former wrapping git_config_open_default and the latter wrapping git_repository_config/git_repository_config_snapshot. Both of these subclasses can now act as context managers for in-memory config overrides. An in-memory backend attached with level APP supports these overrides. When the context manager is entered, the in-memory backend is made the highest priority for writes. When the context manager is exited, the in-memory backend is cleared and made the lowest priority for writes. Within the scope of this context manager, Git operations use these overrides. A hypothetical Python-based alternative Git CLI could, then, implement -c and --config-env using this context manager.
The detailed documentation I have written for these classes explains in more detail.
When using the
gitCLI, you can temporarily override / add config values with-c <name>=<value>(and also--config-env=<name>=<envvar>, but that's just a wrapper around-cto keep secret values off the command line). The important key to-cis that it doesn't persist to a file—the config value lives only so long as that process executes, and then it goes away. Pygit2 has no such support for temporary overrides like this—any changes to aConfigpersist to disk.libgit2 can support this using config backends. Currently, libgit2 comes with two kinds of config backends—file backends (the standard type) and a read-only in-memory backend constructed from strings. We could, in theory, use the read-only in-memory backend, but its use wouldn't be very Pythonic, and also it's not until the unreleased libgit 1.9.5 that it's possible to construct this backend from the public API (prior to 1.9.5, it was private).
But libgit2's public API supports implementing and attaching any arbitrary custom backend, and it's fairly straightforward (if not verbose) to implement a mutable in-memory backend with CFFI + Python.
As an aside, pygit2 is also lacking a wrapper around
git_config_open_default, which is relevant to the approach I'm taking.With the pull request I'm posting shortly,
Config(without any public API breakage) becomes a fully-functional base class that, on its own, does what it has always done: wraps access to configuration files. Two new classesDefaultConfigandRepositoryConfignow extendConfig: the former wrappinggit_config_open_defaultand the latter wrappinggit_repository_config/git_repository_config_snapshot. Both of these subclasses can now act as context managers for in-memory config overrides. An in-memory backend attached with levelAPPsupports these overrides. When the context manager is entered, the in-memory backend is made the highest priority for writes. When the context manager is exited, the in-memory backend is cleared and made the lowest priority for writes. Within the scope of this context manager, Git operations use these overrides. A hypothetical Python-based alternative Git CLI could, then, implement-cand--config-envusing this context manager.The detailed documentation I have written for these classes explains in more detail.