nixpkgs/pkgs/applications/editors/vscode/generic.nix
iosmanthus 6081ff43ee
vscode: Fix url handler MimeType for vscode-insiders
According to upstream RPMs, while using vscode-insiders, the URL handler MimeType should be
`x-scheme-handler/vscode-insiders` instead of `x-scheme-handler/vscode`.

See pull request 293460 and pull request 288425.
2024-03-06 23:03:16 +08:00

259 lines
8.0 KiB
Nix

{ stdenv
, lib
, makeDesktopItem
, unzip
, libsecret
, libXScrnSaver
, libxshmfence
, buildPackages
, at-spi2-atk
, autoPatchelfHook
, alsa-lib
, mesa
, nss
, nspr
, xorg
, systemd
, fontconfig
, libdbusmenu
, glib
, buildFHSEnv
, wayland
, libglvnd
, libkrb5
# Populate passthru.tests
, tests
# needed to fix "Save as Root"
, asar
, bash
# Attributes inherit from specific versions
, version
, src
, meta
, sourceRoot
, commandLineArgs
, executableName
, longName
, shortName
, pname
, updateScript
, dontFixup ? false
, rev ? null
, vscodeServer ? null
, sourceExecutableName ? executableName
, useVSCodeRipgrep ? false
, ripgrep
}:
stdenv.mkDerivation (finalAttrs:
let
# Vscode and variants allow for users to download and use extensions
# which often include the usage of pre-built binaries.
# This has been an on-going painpoint for many users, as
# a full extension update cycle has to be done through nixpkgs
# in order to create or update extensions.
# See: #83288 #91179 #73810 #41189
#
# buildFHSEnv allows for users to use the existing vscode
# extension tooling without significant pain.
fhs = { additionalPkgs ? pkgs: [ ] }: buildFHSEnv {
# also determines the name of the wrapped command
name = executableName;
# additional libraries which are commonly needed for extensions
targetPkgs = pkgs: (with pkgs; [
# ld-linux-x86-64-linux.so.2 and others
glibc
# dotnet
curl
icu
libunwind
libuuid
lttng-ust
openssl
zlib
# mono
krb5
]) ++ additionalPkgs pkgs;
extraBwrapArgs = [
"--bind-try /etc/nixos/ /etc/nixos/"
];
# symlink shared assets, including icons and desktop entries
extraInstallCommands = ''
ln -s "${finalAttrs.finalPackage}/share" "$out/"
'';
runScript = "${finalAttrs.finalPackage}/bin/${executableName}";
# vscode likes to kill the parent so that the
# gui application isn't attached to the terminal session
dieWithParent = false;
passthru = {
inherit executableName;
inherit (finalAttrs.finalPackage) pname version; # for home-manager module
};
meta = meta // {
description = ''
Wrapped variant of ${pname} which launches in a FHS compatible environment.
Should allow for easy usage of extensions without nix-specific modifications.
'';
};
};
in
{
inherit pname version src sourceRoot dontFixup;
passthru = {
inherit executableName longName tests updateScript;
fhs = fhs { };
fhsWithPackages = f: fhs { additionalPkgs = f; };
} // lib.optionalAttrs (vscodeServer != null) {
inherit rev vscodeServer;
};
desktopItem = makeDesktopItem {
name = executableName;
desktopName = longName;
comment = "Code Editing. Redefined.";
genericName = "Text Editor";
exec = "${executableName} %F";
icon = "vs${executableName}";
startupNotify = true;
startupWMClass = shortName;
categories = [ "Utility" "TextEditor" "Development" "IDE" ];
mimeTypes = [ "text/plain" "inode/directory" ];
keywords = [ "vscode" ];
actions.new-empty-window = {
name = "New Empty Window";
exec = "${executableName} --new-window %F";
icon = "vs${executableName}";
};
};
urlHandlerDesktopItem = makeDesktopItem {
name = executableName + "-url-handler";
desktopName = longName + " - URL Handler";
comment = "Code Editing. Redefined.";
genericName = "Text Editor";
exec = executableName + " --open-url %U";
icon = "vs${executableName}";
startupNotify = true;
categories = [ "Utility" "TextEditor" "Development" "IDE" ];
mimeTypes = [ "x-scheme-handler/vs${executableName}" ];
keywords = [ "vscode" ];
noDisplay = true;
};
buildInputs = [ libsecret libXScrnSaver libxshmfence ]
++ lib.optionals (!stdenv.isDarwin) [ alsa-lib at-spi2-atk libkrb5 mesa nss nspr systemd xorg.libxkbfile ];
runtimeDependencies = lib.optionals stdenv.isLinux [ (lib.getLib systemd) fontconfig.lib libdbusmenu wayland libsecret ];
nativeBuildInputs = [ unzip ]
++ lib.optionals stdenv.isLinux [
autoPatchelfHook
asar
# override doesn't preserve splicing https://github.com/NixOS/nixpkgs/issues/132651
(buildPackages.wrapGAppsHook.override { inherit (buildPackages) makeWrapper; })
];
dontBuild = true;
dontConfigure = true;
noDumpEnvVars = true;
installPhase = ''
runHook preInstall
'' + (if stdenv.isDarwin then ''
mkdir -p "$out/Applications/${longName}.app" "$out/bin"
cp -r ./* "$out/Applications/${longName}.app"
ln -s "$out/Applications/${longName}.app/Contents/Resources/app/bin/${sourceExecutableName}" "$out/bin/${executableName}"
'' else ''
mkdir -p "$out/lib/vscode" "$out/bin"
cp -r ./* "$out/lib/vscode"
ln -s "$out/lib/vscode/bin/${sourceExecutableName}" "$out/bin/${executableName}"
mkdir -p "$out/share/applications"
ln -s "$desktopItem/share/applications/${executableName}.desktop" "$out/share/applications/${executableName}.desktop"
ln -s "$urlHandlerDesktopItem/share/applications/${executableName}-url-handler.desktop" "$out/share/applications/${executableName}-url-handler.desktop"
# These are named vscode.png, vscode-insiders.png, etc to match the name in upstream *.deb packages.
mkdir -p "$out/share/pixmaps"
cp "$out/lib/vscode/resources/app/resources/linux/code.png" "$out/share/pixmaps/vs${executableName}.png"
# Override the previously determined VSCODE_PATH with the one we know to be correct
sed -i "/ELECTRON=/iVSCODE_PATH='$out/lib/vscode'" "$out/bin/${executableName}"
grep -q "VSCODE_PATH='$out/lib/vscode'" "$out/bin/${executableName}" # check if sed succeeded
# Remove native encryption code, as it derives the key from the executable path which does not work for us.
# The credentials should be stored in a secure keychain already, so the benefit of this is questionable
# in the first place.
rm -rf $out/lib/vscode/resources/app/node_modules/vscode-encrypt
'') + ''
runHook postInstall
'';
preFixup = ''
gappsWrapperArgs+=(
# Add gio to PATH so that moving files to the trash works when not using a desktop environment
--prefix PATH : ${glib.bin}/bin
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations}}"
--add-flags ${lib.escapeShellArg commandLineArgs}
)
'';
# See https://github.com/NixOS/nixpkgs/issues/49643#issuecomment-873853897
# linux only because of https://github.com/NixOS/nixpkgs/issues/138729
postPatch = lib.optionalString stdenv.isLinux ''
# this is a fix for "save as root" functionality
packed="resources/app/node_modules.asar"
unpacked="resources/app/node_modules"
asar extract "$packed" "$unpacked"
substituteInPlace $unpacked/@vscode/sudo-prompt/index.js \
--replace "/usr/bin/pkexec" "/run/wrappers/bin/pkexec" \
--replace "/bin/bash" "${bash}/bin/bash"
rm -rf "$packed"
# without this symlink loading JsChardet, the library that is used for auto encoding detection when files.autoGuessEncoding is true,
# fails to load with: electron/js2c/renderer_init: Error: Cannot find module 'jschardet'
# and the window immediately closes which renders VSCode unusable
# see https://github.com/NixOS/nixpkgs/issues/152939 for full log
ln -rs "$unpacked" "$packed"
'' + (
let
vscodeRipgrep =
if stdenv.isDarwin then
"Contents/Resources/app/node_modules.asar.unpacked/@vscode/ripgrep/bin/rg"
else
"resources/app/node_modules/@vscode/ripgrep/bin/rg";
in
if !useVSCodeRipgrep then ''
rm ${vscodeRipgrep}
ln -s ${ripgrep}/bin/rg ${vscodeRipgrep}
'' else ''
chmod +x ${vscodeRipgrep}
''
);
postFixup = lib.optionalString stdenv.isLinux ''
patchelf \
--add-needed ${libglvnd}/lib/libGLESv2.so.2 \
--add-needed ${libglvnd}/lib/libGL.so.1 \
--add-needed ${libglvnd}/lib/libEGL.so.1 \
$out/lib/vscode/${executableName}
'';
inherit meta;
})