ipfs / kubo

An IPFS implementation in Go
https://docs.ipfs.tech/how-to/command-line-quick-start/
Other
16.04k stars 3k forks source link

`ipfs config edit` doesn't handle EDITOR env var properly #9375

Open SgtPooki opened 1 year ago

SgtPooki commented 1 year ago

Checklist

Installation method

ipfs-update or dist.ipfs.tech

Version

╰─ ✔ ❯ ipfs version --all
Kubo version: 0.16.0-rc1-d4ac65f43
Repo version: 12
System version: arm64/darwin
Golang version: go1.18.4

Config

{
  "API": {
    "HTTPHeaders": {
      "Access-Control-Allow-Methods": [
        "PUT",
        "POST"
      ],
      "Access-Control-Allow-Origin": [
        "http://localhost:3000",
        "http://127.0.0.1:5001",
        "https://webui.ipfs.io",
        "*"
      ]
    }
  },
  "Addresses": {
    "API": "/ip4/127.0.0.1/tcp/5002",
    "Announce": [],
    "AppendAnnounce": [],
    "Gateway": "/ip4/127.0.0.1/tcp/8081",
    "NoAnnounce": [],
    "Swarm": [
      "/ip4/0.0.0.0/tcp/4001",
      "/ip6/::/tcp/4001",
      "/ip4/0.0.0.0/udp/4001/quic",
      "/ip6/::/udp/4001/quic",
      "/ip4/0.0.0.0/udp/4002/quic/webtransport"
    ]
  },
  "AutoNAT": {},
  "Bootstrap": [
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
    "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
    "/ip4/104.131.131.82/udp/4001/quic/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
  ],
  "DNS": {
    "Resolvers": {}
  },
  "Datastore": {
    "BloomFilterSize": 0,
    "GCPeriod": "1h",
    "HashOnRead": false,
    "Spec": {
      "mounts": [
        {
          "child": {
            "path": "blocks",
            "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
            "sync": true,
            "type": "flatfs"
          },
          "mountpoint": "/blocks",
          "prefix": "flatfs.datastore",
          "type": "measure"
        },
        {
          "child": {
            "compression": "none",
            "path": "datastore",
            "type": "levelds"
          },
          "mountpoint": "/",
          "prefix": "leveldb.datastore",
          "type": "measure"
        }
      ],
      "type": "mount"
    },
    "StorageGCWatermark": 90,
    "StorageMax": "10GB"
  },
  "Discovery": {
    "MDNS": {
      "Enabled": true,
      "Interval": 10
    }
  },
  "Experimental": {
    "AcceleratedDHTClient": false,
    "FilestoreEnabled": false,
    "GraphsyncEnabled": false,
    "Libp2pStreamMounting": false,
    "P2pHttpProxy": false,
    "StrategicProviding": false,
    "UrlstoreEnabled": false
  },
  "Gateway": {
    "APICommands": [],
    "HTTPHeaders": {
      "Access-Control-Allow-Headers": [
        "X-Requested-With",
        "Range",
        "User-Agent"
      ],
      "Access-Control-Allow-Methods": [
        "GET"
      ],
      "Access-Control-Allow-Origin": [
        "*"
      ]
    },
    "NoDNSLink": false,
    "NoFetch": false,
    "PathPrefixes": [],
    "PublicGateways": null,
    "RootRedirect": "",
    "Writable": false
  },
  "Identity": {
    "PeerID": "12D3KooWMBeKmccSU6Jx69sZgCNBKdWwkvM8u3mBN8XEyzG4jLWY"
  },
  "Internal": {},
  "Ipns": {
    "RecordLifetime": "",
    "RepublishPeriod": "",
    "ResolveCacheSize": 128
  },
  "Migration": {
    "DownloadSources": [],
    "Keep": ""
  },
  "Mounts": {
    "FuseAllowOther": false,
    "IPFS": "/ipfs",
    "IPNS": "/ipns"
  },
  "Peering": {
    "Peers": null
  },
  "Pinning": {
    "RemoteServices": {
      "Estuary": {
        "API": {
          "Endpoint": "https://api.estuary.tech/pinning"
        },
        "Policies": {
          "MFS": {
            "Enable": false,
            "PinName": "",
            "RepinInterval": ""
          }
        }
      },
      "Pinata": {
        "API": {
          "Endpoint": "https://api.pinata.cloud/psa"
        },
        "Policies": {
          "MFS": {
            "Enable": false,
            "PinName": "",
            "RepinInterval": ""
          }
        }
      },
      "Web3_Storage": {
        "API": {
          "Endpoint": "https://api.web3.storage"
        },
        "Policies": {
          "MFS": {
            "Enable": false,
            "PinName": "",
            "RepinInterval": ""
          }
        }
      }
    }
  },
  "Plugins": {
    "Plugins": null
  },
  "Provider": {
    "Strategy": ""
  },
  "Pubsub": {
    "DisableSigning": false,
    "Router": ""
  },
  "Reprovider": {
    "Interval": "12h",
    "Strategy": "all"
  },
  "Routing": {
    "Methods": null,
    "Routers": null,
    "Type": "dht"
  },
  "Swarm": {
    "AddrFilters": null,
    "ConnMgr": {
      "GracePeriod": "1m",
      "HighWater": 40,
      "LowWater": 20,
      "Type": "basic"
    },
    "DisableBandwidthMetrics": false,
    "DisableNatPortMap": false,
    "RelayClient": {},
    "RelayService": {},
    "ResourceMgr": {},
    "Transports": {
      "Multiplexers": {},
      "Network": {
        "WebTransport": true
      },
      "Security": {}
    }
  }
}

Description

The bug is that I cannot run ipfs config edit because my EDITOR environment variable is more than a single path to an executable.

╭─    ~/code/work/protocol.ai/ipfs/js-kubo-rpc-client    fix/update-d…on-and-tests
╰─ ✘ INT ❯ echo $EDITOR
code --wait

╭─    ~/code/work/protocol.ai/ipfs/js-kubo-rpc-client    fix/update-d…on-and-tests
╰─ ✔ ❯ ipfs config edit
Error: exec: "code --wait": executable file not found in $PATH

╭─    ~/code/work/protocol.ai/ipfs/js-kubo-rpc-client    fix/update-d…on-and-tests
╰─ ✘ 1 ❯ where code
/opt/homebrew/bin/code

╭─    ~/code/work/protocol.ai/ipfs/js-kubo-rpc-client    fix/update-d…on-and-tests
╰─ ✔ ❯ which code
/opt/homebrew/bin/code

╭─    ~/code/work/protocol.ai/ipfs/js-kubo-rpc-client    fix/update-d…on-and-tests
╰─ ✔ ❯ EDITOR="/opt/homebrew/bin/code --wait" ipfs config edit                                                                                           9.57   25.2G   23%   36%  ─╯
Error: fork/exec /opt/homebrew/bin/code --wait: no such file or directory

The following commands do work:

welcome[bot] commented 1 year ago

Thank you for submitting your first issue to this repository! A maintainer will be here shortly to triage and review. In the meantime, please double-check that you have provided all the necessary information to make this process easy! Any information that can help save additional round trips is useful! We currently aim to give initial feedback within two business days. If this does not happen, feel free to leave a comment. Please keep an eye on how this issue will be labeled, as labels give an overview of priorities, assignments and additional actions requested by the maintainers:

Finally, remember to use https://discuss.ipfs.io if you just need general support.

Jorropo commented 1 year ago

Ah sorry I broke this in https://github.com/ipfs/kubo/pull/9014.

We are not parsing the arguments, we would need to call "code", "--wait", filename but we are doing "code --wait", filename. Doing strings.Split(editor, " ") isn't enough because spaces in " must not be broken, there is also other edge cases like \".

I hope someone already wrote a lib to parse a string into an argv array, I don't want to call the shell again and have os specific edge cases.

Jorropo commented 1 year ago

If anyone want to pick this up, I found that this is available in glibc as wordexp, hopefully searching for golang wordexp is gonna help you, I hope we can use a go native implementation, I don't feel we should use CGO for this.