Need help with isomorphic-git not being able to fetch git.log due to TypeError (reading 'bind')

I spent two days trying to figure this out. But I’m very new to typescript and plugin development.
I want to fetch the logs of my vault stored in git using isomorphic-git (because it allegedly works on mobile too).
Here is what I came up with so far, simply extending the sample plugin:

import * as git from 'isomorphic-git';

	async onload() {

		this.addCommand({
			id: 'output-git-log',
			name: 'Output Git Log',
			callback: () => this.outputGitLog(),
		});

	async outputGitLog() {
        const dir = this.app.vault.getRoot().path;
        const log = await git.log({ fs: this.app.vault.adapter, dir });
    }

This is the error I’m getting:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'bind')
    at bindFs (plugin:sample-plugin:8477:68)
    at new FileSystem (plugin:sample-plugin:8497:7)
    at log (plugin:sample-plugin:8997:11)
    at MyPlugin.outputGitLog (plugin:sample-plugin:9075:24)
    at Object.callback (plugin:sample-plugin:9057:28)
    at pj (app.js:1:1965818)
    at t.onChooseItem (app.js:1:2612161)
    at t.onChooseSuggestion (app.js:1:1795118)
    at t.selectSuggestion (app.js:1:1794588)
    at e.useSelectedItem (app.js:1:1378259)

It seems to me that the file system does not support bind(). I looked into the source of obsidian-git and as far as I can tell it uses vault.adapter with isomorphic-git:
Vinzent03/obsidian-git/blob/d2991ccedcd59c56e685c2c776159f236bad8331/src/gitManager/myAdapter.ts#L23C24-L23C37
I experimented with LightningFS too, trying to follow the instructions on the homepage of isomorphic-git. Didn’t succeed with that either.

Please can someone shed a light on what I am doing wrong? I am out of ideas and also lacking enough knowledge.

from the git plugin source code these are the parameters for the log() command on mobile:

 async log(
        _?: string,
        __ = true,
        limit?: number,
        ref?: string
    ): Promise<LogEntry[]>

ive only worked with simplegit so far and it had weird rules for passing custom arguments, idk how it works for isomorphic git

what is your “fs” parameter?

the fs parameter is

this.app.vault.adapter

Are you suggesting there is a parameter missing when I call git.log()?

The error Cannot read properties of undefined suggests to me that this.app.vault.adapter is undefined when the plugin is trying to bind the file system. Why is that?

I didn’t look into it too deep but from the first look I don’t see the “fs” parameter in the available parameters for the log function. where are you getting that?

this.app.vault.adapter

is undefined because you are unnecessarily trying to access it through the obsidian git plugin while you can access it from your plugin.

from:

this.app.plugins.getPlugin("obsidian-git").app.vault.adapter

to:

this.app.vault.adapter

(inside the plugin class)

but that still doesn’t solve the problem of you trying to assign this value to a non-existent “fs” parameter for the log function

It is mandatory (on the isomorphic-git homepage /docs/en/log) in the code you quoted also:

    async log(
        _?: string,
        __ = true,
        limit?: number,
        ref?: string
    ): Promise<LogEntry[]> {
        const logs = await this.wrapFS(
            git.log({ ...this.getRepo(), depth: limit, ref: ref })
        );

yes, that was only a desperate try to make it work.

I think you’re confusing the raw mertic isomorphic-git log command with the obsidian git plugin wrapper over that command (same name= log() ?).

the function that I shared was the already wrapped function, that’s why I suggested to use it in the first place

the developer of obsidian git plugin probably already dealt with the headaches of isomorphic git

you mixed up the definition of git.log in obsidian-git and isomorphic-git.
This is only a wrapper:

    async log(
        _?: string,
        __ = true,
        limit?: number,
        ref?: string
    ): Promise<LogEntry[]> {
        const logs = await this.wrapFS(
            git.log({ ...this.getRepo(), depth: limit, ref: ref })
        );

from the code you shared you’re trying to access the git variable and only then call the log command , but the git variable is exclusively an instance of simple git meant for desktop

if you want to call isomorphic git wrapper comman, you should emit the git variable

from

this.app.plugins.getPlugin("obsidian-git").gitManager.git.log()

to

this.app.plugins.getPlugin("obsidian-git").gitManager.log()


and this way you’re just calling the wrapper function and then the original isomorphic git function is being handled inside the log function you’re calling

and you probably need to do additional checks like

gitManager instanceof IsomorphicGit

and

gitManager instanceof SimpleGit

if you check the obsidian git plugin it contains a lot of these checks, so thats probably the intended way to use it

also im not 100% sure on things i said so keep that in mind

gitManager is a custom wrapper for isomorphic-git and simplegit in the plugin obsidian-git. I don’t need all that, I just want to use isomorphic-git plainly.

okay, then the things i said dont matter, and you dont need any dependencies on the git plugin at all, but you lose this benefit i mentioned:

handle all git operations through git plugin, so that if user has some custom git config, they don’t have to configure each plugin separately

but most users probably wont change their git repo configurations.

I think that it’s still easier to work with isomorphic git through the obsidian git plugin but if you don’t want that then I probably can’t help much because I have no experience with isomorphic git

You do know that the adapter property isn’t a string but a custom type “DataAdapter”?

yes, and I hope that corresponds to fs which should be a “a file system client”. Is DataAdapter a “file system client”?

I also tried this.app.vault.adapter.fs , same error.

you could just inspect how the obsidian git plugin handles it since you’re trying to run the same command

const logs = await this.wrapFS(
            git.log({ ...this.getRepo(), depth: limit, ref: ref })
        );
getRepo(): {
        fs: MyAdapter;
        dir: string;
        gitdir?: string;
        onAuth: AuthCallback;
        onAuthFailure: AuthFailureCallback;
        http: HttpClient;
    } {
        return {
            fs: this.fs,

    ...

Yup, I did that, MyAdapter is simply

this.adapter = vault.adapter

DataAdapter and it’s implementations are Obsidian specific, they won’t be what the library is expecting.

Also, random question, but if the Git plugin already has that function, why do you want to build your own plugin?

1 Like