Skip to content

feat: allow custom ipfs binary #1427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
"moveRepositoryLocation": "Move Repository Location",
"runGarbageCollector": "Run Garbage Collector",
"selectDirectory": "Select Directory",
"customIpfsBinary": "Custom IPFS Binary",
"setCustomIpfsBinary": "Set Custom IPFS Binary",
"clearCustomIpfsBinary": "Clear Custom IPFS Binary",
"polkitDialog": {
"title": "Polkit not found",
"message": "IPFS can't be added to /usr/local/bin/ without polkit agent."
Expand Down Expand Up @@ -224,5 +227,17 @@
"downloadHashShortcut": "Global Download Shortcut",
"experiments": "Experiments",
"npmOnIpfs": "npm on IPFS"
},
"setCustomIpfsBinaryConfirmation": {
"title": "Custom IPFS binary",
"message": "By setting a custom IPFS, IPFS Desktop will no longer use the bundled IPFS version and will use the binary you specify. Do you wish to proceed?"
},
"setCustomIpfsBinarySuccess": {
"title": "Custom IPFS binary",
"message": "IPFS Desktop will start using the binary located at { path }. To start using it, IPFS needs to be restarted first."
},
"clearCustomIpfsBinarySuccess": {
"title": "Clear custom IPFS binary",
"message": "The custom IPFS binary was cleared. To start using the bundled IPFS version, IPFS needs to be restarted first."
}
}
93 changes: 93 additions & 0 deletions src/custom-ipfs-binary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const i18n = require('i18next')
const { app, dialog } = require('electron')
const { showDialog } = require('./dialogs')
const logger = require('./common/logger')
const store = require('./common/store')
const dock = require('./utils/dock')

const SETTINGS_KEY = 'binaryPath'

async function setCustomBinary (ctx) {
await dock.run(async () => {
logger.info('[custom binary] request to change')
let opt = showDialog({
showDock: false,
title: i18n.t('setCustomIpfsBinaryConfirmation.title'),
message: i18n.t('setCustomIpfsBinaryConfirmation.message'),
type: 'warning',
buttons: [
i18n.t('yes'),
i18n.t('no')
]
})

if (opt !== 0) {
logger.info('[custom binary] user canceled')
return
}

const { canceled, filePaths } = await dialog.showOpenDialog({
title: i18n.t('pickCustomIpfsBinary'),
defaultPath: app.getPath('home'),
properties: ['openFile']
})

if (canceled || filePaths.length === 0) {
logger.info('[custom binary] user canceled')
return
}

store.set(SETTINGS_KEY, filePaths[0])

opt = showDialog({
showDock: false,
title: i18n.t('setCustomIpfsBinarySuccess.title'),
message: i18n.t('setCustomIpfsBinarySuccess.message', { path: filePaths[0] }),
buttons: [
i18n.t('restart'),
i18n.t('close')
]
})

logger.info(`[custom binary] updated to ${filePaths[0]}`)

if (opt === 0) {
ctx.restartIpfs()
}
})
}

function clearCustomBinary (ctx) {
store.delete(SETTINGS_KEY)
logger.info('[custom binary] cleared')

const opt = showDialog({
title: i18n.t('clearCustomIpfsBinarySuccess.title'),
message: i18n.t('clearCustomIpfsBinarySuccess.message'),
buttons: [
i18n.t('restart'),
i18n.t('close')
]
})

if (opt === 0) {
ctx.restartIpfs()
}
}

function hasCustomBinary () {
return typeof store.get(SETTINGS_KEY) === 'string'
}

function getCustomBinary () {
if (hasCustomBinary()) {
return store.get(SETTINGS_KEY)
}
}

module.exports = {
setCustomBinary,
clearCustomBinary,
hasCustomBinary,
getCustomBinary
}
25 changes: 21 additions & 4 deletions src/daemon/daemon.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
const Ctl = require('ipfsd-ctl')
const i18n = require('i18next')
const fs = require('fs-extra')
const { join } = require('path')
const { app } = require('electron')
const { showDialog } = require('../dialogs')
const logger = require('../common/logger')
const { applyDefaults, checkCorsConfig, checkPorts, configExists, rmApiFile, apiFileExists } = require('./config')
const { getCustomBinary } = require('../custom-ipfs-binary')

function cannotConnectDialog (addr) {
showDialog({
Expand All @@ -16,15 +20,28 @@ function cannotConnectDialog (addr) {
}

function getIpfsBinPath () {
return require('go-ipfs-dep')
.path()
.replace('app.asar', 'app.asar.unpacked')
return process.env.IPFS_GO_EXEC ||
getCustomBinary() ||
require('go-ipfs-dep')
.path()
.replace('app.asar', 'app.asar.unpacked')
}

function writeIpfsBinaryPath (path) {
fs.outputFileSync(
join(app.getPath('home'), './.ipfs-desktop/IPFS_EXEC')
.replace('app.asar', 'app.asar.unpacked'),
path
)
}

async function spawn ({ flags, path, keysize }) {
const ipfsBin = getIpfsBinPath()
writeIpfsBinaryPath(ipfsBin)

const ipfsd = await Ctl.createController({
ipfsHttpModule: require('ipfs-http-client'),
ipfsBin: getIpfsBinPath(),
ipfsBin,
ipfsOptions: {
repo: path
},
Expand Down
3 changes: 2 additions & 1 deletion src/ipfs-on-path/scripts/bin-win/ipfs.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ if exist "%USERPROFILE%\.ipfs-desktop\IPFS_PATH" (
SET /P IPFS_PATH=<"%USERPROFILE%\.ipfs-desktop\IPFS_PATH"
)

"%~dp0\..\..\..\..\node_modules\go-ipfs-dep\go-ipfs\ipfs.exe" %*
SET /P IPFS_EXEC=<"%USERPROFILE%\.ipfs-desktop\IPFS_EXEC"
%IPFS_EXEC% %*
3 changes: 2 additions & 1 deletion src/ipfs-on-path/scripts/ipfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ fi

# Get the full path of the app directory (resolving the symlink if needed)
app=$(dirname "$(dirname "$(dirname "$dir")")")

# Get the full path to ipfs binary bundled with ipfs-desktop
ipfs="$app/node_modules/go-ipfs-dep/go-ipfs/ipfs"
ipfs="$(cat ~/.ipfs-desktop/IPFS_EXEC)"

exec "$ipfs" "$@"
29 changes: 24 additions & 5 deletions src/tray.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const logger = require('./common/logger')
const store = require('./common/store')
const moveRepositoryLocation = require('./move-repository-location')
const runGarbageCollector = require('./run-gc')
const { setCustomBinary, clearCustomBinary, hasCustomBinary } = require('./custom-ipfs-binary')
const { STATUS } = require('./daemon')
const { IS_MAC, IS_WIN, VERSION, GO_IPFS_VERSION } = require('./common/consts')

Expand Down Expand Up @@ -145,16 +146,29 @@ function buildMenu (ctx) {
click: () => { shell.openItem(store.path) }
},
{ type: 'separator' },
{
id: 'runGarbageCollector',
label: i18n.t('runGarbageCollector'),
click: () => { runGarbageCollector(ctx) },
enabled: false
},
{ type: 'separator' },
{
id: 'moveRepositoryLocation',
label: i18n.t('moveRepositoryLocation'),
click: () => { moveRepositoryLocation(ctx) }
},
{
id: 'runGarbageCollector',
label: i18n.t('runGarbageCollector'),
click: () => { runGarbageCollector(ctx) },
enabled: false
id: 'setCustomBinary',
label: i18n.t('setCustomIpfsBinary'),
click: () => { setCustomBinary(ctx) },
visible: false
},
{
id: 'clearCustomBinary',
label: i18n.t('clearCustomIpfsBinary'),
click: () => { clearCustomBinary(ctx) },
visible: false
}
]
},
Expand All @@ -170,7 +184,9 @@ function buildMenu (ctx) {
click: () => { shell.openExternal('https://github.com/ipfs-shipyard/ipfs-desktop/releases') }
},
{
label: `go-ipfs ${GO_IPFS_VERSION}`,
label: hasCustomBinary()
? i18n.t('customIpfsBinary')
: `go-ipfs ${GO_IPFS_VERSION}`,
click: () => { shell.openExternal('https://github.com/ipfs/go-ipfs/releases') }
},
{ type: 'separator' },
Expand Down Expand Up @@ -278,6 +294,9 @@ module.exports = function (ctx) {
menu.getMenuItemById('moveRepositoryLocation').enabled = !gcRunning && status !== STATUS.STOPPING_STARTED
menu.getMenuItemById('runGarbageCollector').enabled = menu.getMenuItemById('ipfsIsRunning').visible && !gcRunning

menu.getMenuItemById('setCustomBinary').visible = !hasCustomBinary()
menu.getMenuItemById('clearCustomBinary').visible = hasCustomBinary()

if (status === STATUS.STARTING_FINISHED) {
tray.setImage(icon(on))
} else {
Expand Down