Adding to the output of a CLI command

Hi team,
So, I am just getting started with IPFS and looking at its code. I have a basic task to do, which is to add an arbitrary string to the output of a certain command ( ipfs dht findprovs ). I am very new to go as well as IPFS. Is anyone up for a small meeting where I can learn more about how to go over this task?
A reply describing how to proceed will also be appreciated.

Thanks.

The command engine is a beast.

So the commands live under github.com/ipfs/go-ipfs/core/commands
From here the hiearchy makes sense and you can find the command you are looking for easly (you can also rgrep for the actual command string, rgrep findprovs will show you where it is).

	Subcommands: map[string]*cmds.Command{
		"query":     queryDhtCmd,
		"findprovs": findProvidersDhtCmd,
		"findpeer":  findPeerDhtCmd,
		"get":       getValueDhtCmd,
		"put":       putValueDhtCmd,
		"provide":   provideRefDhtCmd,
	},

This is what you should find, this is the subcommand map of the dht command.
Each string is a subcommand and it point to a command object, that object is what you will need to change.
CTRL + Left Click on findProvidersDhtCmd with go-pls to teleport where it is defined (really go-pls is an awesome tool install it (as well as the required bridging plugin for your editor) it’s free and makes life so much better):

var findProvidersDhtCmd = &cmds.Command{
	Helptext: cmds.HelpText{/* ... */},

	Arguments: []cmds.Argument{/* ... */},
	Options: []cmds.Option{/* ... */},
	Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
		// ...
	},
	Encoders: cmds.EncoderMap{
		cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *routing.QueryEvent) error {
			// ...
		}),
	},
	Type: routing.QueryEvent{},
}

(I’ve shorten this code)
The relevent fields are:

Run:

This is a lambda that will be run SERVER SIDE, it is really important to remember, this is the DEAMON running that.
If you are using offline mode then it is also deamon but it’s the offline one with networking disabled and it run in the same process but let’s ignore that.

This is where your logic goes.
I have insisted a lot on SERVER SIDE because, if you have a deamon running, make a change in the run command, you need to stop your deamon and restart it with a new build containing your change else that will act like it works but it will not (even if your ipfs CLI is updated, if your deamon isn’t, it will use the old code).

And:

Encoders:

This one is more complicated (but you can just copy paste it from an other command).
Basically the Run produce native types (arrays, CIDs, …) and then you have multiple encoders using the same types but to produce different thing.
This is mainly used for the ipfs --enc=json option.
For example:

$ ipfs --enc=text swarm peers
$ ipfs --enc=json swarm peers

Use the same Run lambda but different Encoders that allows to share the “buisness” (logic) code, and have just a new encoder moved into place when needed (that the “rule” you should follow, in most cases make encoders dumb, they only handle encoding, and everything else goes in Run).

1 Like

Hey,
Thanks for the detailed response. I now have a sense of what’s happening.
Now, I made certain changes to the Run block, but don’t see those changes reflected while running the command. I used the below commands to compile go-ipfs:

$ git clone https://github.com/ipfs/go-ipfs.git

$ cd go-ipfs
$ make install

Note: I also had go-ipfs installed using the binary.

Why don’t I see the changes? Also, would you mind describing how we can test our changes to the go-ipfs code?

How are you testing your changes, do you update the deamon ?

Basically.
Aren’t your change on the deamon only ? The Run block is executed in the deamon, not in the CLI.

Also, would you mind describing how we can test our changes to the go-ipfs code?

I don’t have much to say about that sorry, IPFS is golang application, you test it like any other golang application.