Config object is always live - get_str() fails
When attempting to
let cfg = repo.config().expect("Failed to obtain config struct");
let name = cfg.get_str("user.name").unwrap(); // <<< fails here
let email = cfg.get_str("user.email").unwrap();
it always fails with:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -1, klass: 7, message: "get_string called on a live config object" }', src/libcore/result.rs:999:5
stack backtrace:
which I backtraced down to is_readonly returning 1.
int git_config_get_string(
const char **out, const git_config *cfg, const char *name)
{
git_config_entry *entry;
int ret;
if (!is_readonly(cfg)) { // <<<< always fails
git_error_set(GIT_ERROR_CONFIG, "get_string called on a live config object");
return -1;
}
ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
*out = !ret ? (entry->value ? entry->value : "") : NULL;
git_config_entry_free(entry);
return ret;
}
Minimal fully runnable demo of the issue: https://github.com/drahnr/gitconfigtest/
$ git config user.name
Bernhard
works fine
(Or maybe I do not understand the meaning of this error and it's a layer 8 problem)
$ dnf info libgit2
Name : libgit2
Version : 0.27.8
Release : 2.fc30
Architecture : x86_64
Size : 1.2 M
Quelle : libgit2-0.27.8-2.fc30.src.rpm
Repository : @System
Aus Paketque : fedora
Summary : C implementation of the Git core methods as a library with a solid API
<snip>
Interestingly:
for entry in &cfg.entries(None).unwrap() {
let entry = entry.unwrap();
println!("{} => {}", entry.name().unwrap(), entry.value().unwrap());
}
yields:
filter.lfs.clean => git-lfs clean -- %f
filter.lfs.smudge => git-lfs smudge -- %f
filter.lfs.process => git-lfs filter-process
filter.lfs.required => true
user.name => Bernhard
user.email => my github email
core.editor => micro
sequence.editor => interactive-rebase-tool
core.bare => false
core.repositoryformatversion => 0
core.filemode => true
core.logallrefupdates => true
remote.origin.url => [email protected]:drahnr/gitconfigtest.git
remote.origin.fetch => +refs/heads/*:refs/remotes/origin/*
branch.master.remote => origin
branch.master.merge => refs/heads/master
Derived from that:
let name = cfg.get_entry("user.name").unwrap();
let name = name.value().unwrap();
let email = cfg.get_entry("user.email").unwrap();
let email = email.value().unwrap();
works just fine.
So this is probably rather a request clarifying what should be used, since the get_str clearly has some constraints the get_entry does not which is not reflected in the documentation.
Note that the readonly requirment is only present in git_config_get_str but in none of the others:
All others use the git_config_entry APIs internally and thus do not have this check.
I've fallen foul of this exact problem too! It's not clear looking at the upstream c why this behaves this way... Is it worth opening an issue upstream?
I would suggest to fix the binding to use the entry API or at least document it sufficiently :) I never got around to do so though.
I know it's almost 5 years later, but still.
Could you try this?
let cfg = repo.config().expect("Failed to obtain config struct").snapshot().unwrap();
let name = cfg.get_str("user.name").unwrap();
let email = cfg.get_str("user.email").unwrap();
I encountered exactly the same issue - attempt to read anything from config resulted in this error:
Error { code: -1, klass: 7, message: "get_string called on a live config object" }
Not sure why that is, and I don't want to jump to conclusions before inspecting underlying C code. I'm curious though, so I'll definitely do it when I have a moment.
Still broken.
However, this works: repo.config.get_entry()
As a workaround, anywhere that I would use something equivalent to:
repo.config().unwrap().get_str("core.bare").unwrap()
I would instead use:
repo.config().unwrap().get_entry("core.bare").unwrap().value()