From eb942cabd99ee848a8ba61c11977ff69cd2495fc Mon Sep 17 00:00:00 2001 From: jfgordon2 <55799997+jfgordon2@users.noreply.github.com> Date: Sun, 29 Mar 2020 16:01:51 -0500 Subject: [PATCH] add CLI support to Debian package, add Elementary OS shell and editor support (#231) --- app/src/cli/open-desktop.ts | 2 ++ app/src/lib/editors/linux.ts | 17 +++++++++++++++++ app/src/lib/editors/shared.ts | 5 ++++- app/src/lib/shells/linux.ts | 15 +++++++++++++++ app/static/linux/github | 28 ++++++++++++++++++++++++++++ script/linux-after-install.sh | 18 +++++++++++++----- script/linux-after-remove.sh | 4 ++++ 7 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 app/static/linux/github diff --git a/app/src/cli/open-desktop.ts b/app/src/cli/open-desktop.ts index 3398f5b3945..6b33438b6a0 100644 --- a/app/src/cli/open-desktop.ts +++ b/app/src/cli/open-desktop.ts @@ -12,6 +12,8 @@ export function openDesktop(url: string = '') { return ChildProcess.spawn('open', [url], { env }) } else if (__WIN32__) { return ChildProcess.spawn('cmd', ['/c', 'start', url], { env }) + } else if (__LINUX__) { + return ChildProcess.spawn('xdg-open', [url], { env }) } else { throw new Error( `Desktop command line interface not currently supported on platform ${ diff --git a/app/src/lib/editors/linux.ts b/app/src/lib/editors/linux.ts index 66a28ee7245..181beee7c98 100644 --- a/app/src/lib/editors/linux.ts +++ b/app/src/lib/editors/linux.ts @@ -11,6 +11,7 @@ export enum ExternalEditor { SublimeText = 'Sublime Text', Typora = 'Typora', SlickEdit = 'SlickEdit', + ElementaryCode = 'Code', } export function parse(label: string): ExternalEditor | null { @@ -42,6 +43,10 @@ export function parse(label: string): ExternalEditor | null { return ExternalEditor.SlickEdit } + if (label === ExternalEditor.ElementaryCode) { + return ExternalEditor.ElementaryCode + } + return null } @@ -85,6 +90,9 @@ async function getEditorPath(editor: ExternalEditor): Promise { '/opt/slickedit-pro2016/bin/vs', '/opt/slickedit-pro2015/bin/vs', ]) + case ExternalEditor.ElementaryCode: + return getPathIfAvailable('/usr/bin/io.elementary.code') + default: return assertNever(editor, `Unknown editor: ${editor}`) } @@ -103,6 +111,7 @@ export async function getAvailableEditors(): Promise< sublimePath, typoraPath, slickeditPath, + elementaryCodePath, ] = await Promise.all([ getEditorPath(ExternalEditor.Atom), getEditorPath(ExternalEditor.VSCode), @@ -111,6 +120,7 @@ export async function getAvailableEditors(): Promise< getEditorPath(ExternalEditor.SublimeText), getEditorPath(ExternalEditor.Typora), getEditorPath(ExternalEditor.SlickEdit), + getEditorPath(ExternalEditor.ElementaryCode), ]) if (atomPath) { @@ -141,5 +151,12 @@ export async function getAvailableEditors(): Promise< results.push({ editor: ExternalEditor.SlickEdit, path: slickeditPath }) } + if (elementaryCodePath) { + results.push({ + editor: ExternalEditor.ElementaryCode, + path: elementaryCodePath, + }) + } + return results } diff --git a/app/src/lib/editors/shared.ts b/app/src/lib/editors/shared.ts index 3ae86dce69d..14b8c322095 100644 --- a/app/src/lib/editors/shared.ts +++ b/app/src/lib/editors/shared.ts @@ -2,7 +2,10 @@ import * as Darwin from './darwin' import * as Win32 from './win32' import * as Linux from './linux' -export type ExternalEditor = Darwin.ExternalEditor | Win32.ExternalEditor +export type ExternalEditor = + | Darwin.ExternalEditor + | Win32.ExternalEditor + | Linux.ExternalEditor /** Parse the label into the specified shell type. */ export function parse(label: string): ExternalEditor | null { diff --git a/app/src/lib/shells/linux.ts b/app/src/lib/shells/linux.ts index 00420362a2c..43fc061330b 100644 --- a/app/src/lib/shells/linux.ts +++ b/app/src/lib/shells/linux.ts @@ -13,6 +13,7 @@ export enum Shell { Xterm = 'XTerm', Terminology = 'Terminology', Deepin = 'Deepin Terminal', + Elementary = 'Elementary Terminal', } export const Default = Shell.Gnome @@ -54,6 +55,10 @@ export function parse(label: string): Shell { return Shell.Deepin } + if (label === Shell.Elementary) { + return Shell.Elementary + } + return Default } @@ -81,6 +86,8 @@ function getShellPath(shell: Shell): Promise { return getPathIfAvailable('/usr/bin/terminology') case Shell.Deepin: return getPathIfAvailable('/usr/bin/deepin-terminal') + case Shell.Elementary: + return getPathIfAvailable('/usr/bin/io.elementary.terminal') default: return assertNever(shell, `Unknown shell: ${shell}`) } @@ -99,6 +106,7 @@ export async function getAvailableShells(): Promise< xtermPath, terminologyPath, deepinPath, + elementaryPath, ] = await Promise.all([ getShellPath(Shell.Gnome), getShellPath(Shell.Mate), @@ -109,6 +117,7 @@ export async function getAvailableShells(): Promise< getShellPath(Shell.Xterm), getShellPath(Shell.Terminology), getShellPath(Shell.Deepin), + getShellPath(Shell.Elementary), ]) const shells: Array> = [] @@ -148,6 +157,10 @@ export async function getAvailableShells(): Promise< shells.push({ shell: Shell.Deepin, path: deepinPath }) } + if (elementaryPath) { + shells.push({ shell: Shell.Elementary, path: elementaryPath }) + } + return shells } @@ -172,6 +185,8 @@ export function launch( return spawn(foundShell.path, ['-d', path]) case Shell.Deepin: return spawn(foundShell.path, ['-w', path]) + case Shell.Elementary: + return spawn(foundShell.path, ['-w', path]) default: return assertNever(shell, `Unknown shell: ${shell}`) } diff --git a/app/static/linux/github b/app/static/linux/github new file mode 100644 index 00000000000..dfb32bf6ea4 --- /dev/null +++ b/app/static/linux/github @@ -0,0 +1,28 @@ +#!/bin/sh + +if [ ! -L "$0" ]; then + # if path is not a symlink, find relatively + GITHUB_PATH=$(dirname "$(dirname "$(dirname "$(dirname "$0")")")") +else + if command -v readlink >/dev/null; then + # if readlink exists, follow the symlink and then find relatively + SYMLINK=$(readlink -f "$0") + GITHUB_PATH=$(dirname "$(dirname "$(dirname "$(dirname "$SYMLINK")")")") + else + # else use the standard install location + GITHUB_PATH="/opt/GitHub Desktop" + fi +fi +# check if this is a dev install or standard +if [ -f "$GITHUB_PATH/github-desktop-dev" ]; then + BINARY_NAME="github-desktop-dev" +else + BINARY_NAME="github-desktop" +fi + +ELECTRON="$GITHUB_PATH/$BINARY_NAME" +CLI="$GITHUB_PATH/resources/app/cli.js" + +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" + +exit $? diff --git a/script/linux-after-install.sh b/script/linux-after-install.sh index b6f0a7d1f0c..204b930b83d 100644 --- a/script/linux-after-install.sh +++ b/script/linux-after-install.sh @@ -4,13 +4,21 @@ set -e PROFILE_D_FILE="/etc/profile.d/github-desktop.sh" INSTALL_DIR="/opt/${productFilename}" -SCRIPT=$"#!/bin/sh -export PATH=\"$INSTALL_DIR:\$PATH\"" +CLI_DIR="$INSTALL_DIR/resources/app/static" case "$1" in configure) - echo "$SCRIPT" > "${PROFILE_D_FILE}"; - . "${PROFILE_D_FILE}"; + # add executable permissions for CLI interface + chmod +x "$CLI_DIR"/github || : + # check if this is a dev install or standard + if [ -f "$INSTALL_DIR/github-desktop-dev" ]; then + BINARY_NAME="github-desktop-dev" + else + BINARY_NAME="github-desktop" + fi + # create symbolic links to /usr/bin directory + ln -f -s "$INSTALL_DIR"/$BINARY_NAME /usr/bin || : + ln -f -s "$CLI_DIR"/github /usr/bin || : ;; abort-upgrade|abort-remove|abort-deconfigure) @@ -22,4 +30,4 @@ case "$1" in ;; esac -exit 0 +exit 0 \ No newline at end of file diff --git a/script/linux-after-remove.sh b/script/linux-after-remove.sh index 9a73886e2a5..64c0803dec3 100644 --- a/script/linux-after-remove.sh +++ b/script/linux-after-remove.sh @@ -8,6 +8,10 @@ case "$1" in echo "#!/bin/sh" > "${PROFILE_D_FILE}"; . "${PROFILE_D_FILE}"; rm "${PROFILE_D_FILE}"; + # remove symbolic links in /usr/bin directory + unlink /usr/bin/github-desktop || : + unlink /usr/bin/github-desktop-dev || : + unlink /usr/bin/github || : ;; *)