Skip to content
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

pulsar: init at 1.103.0 #221862

Merged
merged 2 commits into from
Apr 6, 2023
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
7 changes: 7 additions & 0 deletions maintainers/maintainer-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2978,6 +2978,13 @@
githubId = 298705;
name = "Cyril Cohen";
};
colamaroro = {
name = "Corentin Rondier";
email = "[email protected]";
github = "colamaroro";
githubId = 12484955;
matrix = "@colamaroro:lovelyrad.io";
};
cole-h = {
name = "Cole Helbling";
email = "[email protected]";
Expand Down
27 changes: 27 additions & 0 deletions pkgs/applications/editors/pulsar/001-patch-wrapper.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--- a/resources/pulsar.sh 2023-03-16 04:11:14.000000000 +0100
+++ b/resources/pulsar.sh 2023-03-24 14:37:13.468813964 +0100
@@ -123,22 +123,9 @@
elif [ $OS == 'Linux' ]; then
SCRIPT=$(readlink -f "$0")

- PULSAR_PATH="/opt/Pulsar/pulsar"
+ # PULSAR_PATH is set-up via `wrapProgram` in the postFixup phase

- #Will allow user to get context menu on cinnamon desktop enviroment
- #Add a check to make sure that DESKTOP_SESSION is set before attempting to grep it
- #expr substr is expecting 3 arguments string, index, length
- #If grep doesnt find anything is provides an empty string which causes the expr: syntax error: missing argument after '8' error - see pulsar-edit/pulsar#174
- #Im also not quite sure why they used grep instead of simply [ "${DESKTOP_SESSION}" == "cinnamon" ]
- if [ -n "${DESKTOP_SESSION}" ] && [ "$(expr substr $(printenv | grep 'DESKTOP_SESSION=') 17 8)" == "cinnamon" ]; then
- #This local path is almost assuredly wrong as it shouldnt exist in a standard install
mkg20001 marked this conversation as resolved.
Show resolved Hide resolved
- ACTION_PATH="resources/linux/desktopenviroment/cinnamon/pulsar.nemo_action"
-
- #Validate the file exists before attempting to copy it
- if [ -f "${ACTION_PATH}" ]; then
- cp "${$ACTION_PATH}" "/usr/share/nemo/actions/pulsar.nemo_action"
- fi
- fi
+ # We remove the nemo integration. It is handled by the postFixup phase

#Set tmpdir only if tmpdir is unset
: ${TMPDIR:=/tmp}
163 changes: 163 additions & 0 deletions pkgs/applications/editors/pulsar/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
{ lib
, stdenv
, git
, runtimeShell
, fetchurl
, wrapGAppsHook
, glib
, gtk3
, atomEnv
, xorg
, libxkbcommon
, hunspell
, hunspellDicts
, useHunspell ? true
, languages ? [ "en_US" ]
, withNemoAction ? true
, makeDesktopItem
, copyDesktopItems
, makeWrapper
}:

let
pname = "Pulsar";
version = "1.103.0";

sourcesPath = {
x86_64-linux.tarname = "Linux.${pname}-${version}.tar.gz";
x86_64-linux.hash = "sha256-C9La+rMpxyFthNPwPBZfV1goP/F1TiNYYYwmPCSkKdw=";
aarch64-linux.tarname = "ARM.Linux.${pname}-${version}-arm64.tar.gz";
aarch64-linux.hash = "sha256-uVGxDLqFgm5USZT6i7pLYJZq8jFxZviVXXYTL3RVhpw=";
}.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");

additionalLibs = lib.makeLibraryPath [
xorg.libxshmfence
libxkbcommon
xorg.libxkbfile
];
newLibpath = "${atomEnv.libPath}:${additionalLibs}";

# Hunspell
hunspellDirs = builtins.map (lang: "${hunspellDicts.${lang}}/share/hunspell") languages;
hunspellTargetDirs = "$out/opt/Pulsar/resources/app.asar.unpacked/node_modules/spellchecker/vendor/hunspell_dictionaries";
hunspellCopyCommands = lib.concatMapStringsSep "\n" (lang: "cp -r ${lang}/* ${hunspellTargetDirs};") hunspellDirs;
in
stdenv.mkDerivation rec {
inherit pname version;

src = with sourcesPath; fetchurl {
url = "https://github.com/pulsar-edit/pulsar/releases/download/v${version}/${tarname}";
inherit hash;
};

patches = [
./001-patch-wrapper.patch
];

nativeBuildInputs = [
wrapGAppsHook
copyDesktopItems
];
COLAMAroro marked this conversation as resolved.
Show resolved Hide resolved

buildInputs = [
gtk3
xorg.libxkbfile
];

dontBuild = true;
dontConfigure = true;

installPhase = ''
runHook preInstall

mkdir -p $out/opt/Pulsar
mv * $out/opt/Pulsar

runHook postInstall
'';

preFixup = ''
gappsWrapperArgs+=(
# needed for gio executable to be able to delete files
--prefix "PATH" : "${lib.makeBinPath [ glib ]}"
)
'' + lib.optionalString useHunspell ''
# On all platforms, we must inject our dictionnaries
${hunspellCopyCommands}
'';

postFixup = ''
opt=$out/opt/Pulsar
# Patch the prebuilt binaries
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--set-rpath "${newLibpath}:$opt" \
--add-needed libffmpeg.so \
--add-needed libxshmfence.so.1 \
--add-needed libxkbcommon.so.0 \
--add-needed libxkbfile.so.1 \
--add-needed libsecret-1.so.0 \
$opt/pulsar
SuperSandro2000 marked this conversation as resolved.
Show resolved Hide resolved
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
--set-rpath "${newLibpath}" \
$opt/resources/app/ppm/bin/node
patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
$opt/resources/app.asar.unpacked/node_modules/symbols-view/vendor/ctags-linux

'' + lib.optionalString (stdenv.hostPlatform.system == "x86_64-linux") ''
# Replace the bundled git with the one from nixpkgs
dugite=$opt/resources/app.asar.unpacked/node_modules/dugite
rm -f $dugite/git/bin/git
ln -s ${git}/bin/git $dugite/git/bin/git
rm -f $dugite/git/libexec/git-core/git
ln -s ${git}/bin/git $dugite/git/libexec/git-core/git
SuperSandro2000 marked this conversation as resolved.
Show resolved Hide resolved
'' + ''
# Patch the bundled node executables
find $opt -name "*.node" -exec patchelf --set-rpath "${newLibpath}:$opt" {} \;
# Also patch the node executable for apm
patchelf --set-rpath "${newLibpath}:$opt" $opt/resources/app/ppm/bin/node

# We have patched the original wrapper, but now it needs the "PULSAR_PATH" env var
mkdir -p $out/bin
wrapProgram $opt/resources/pulsar.sh \
--prefix "PULSAR_PATH" : "$opt/pulsar"
ln -s $opt/resources/pulsar.sh $out/bin/pulsar
ln -s $opt/resources/app/ppm/bin/apm $out/bin/ppm

# Copy the icons
mkdir -p $out/share/icons/hicolor/scalable/apps $out/share/icons/hicolor/1024x1024/apps
cp $opt/resources/pulsar.svg $out/share/icons/hicolor/scalable/apps/pulsar.svg
cp $opt/resources/pulsar.png $out/share/icons/hicolor/1024x1024/apps/pulsar.png
'' + lib.optionalString withNemoAction ''
# Copy the nemo action file
mkdir -p $out/share/nemo/actions
cp ${./pulsar.nemo_action} $out/share/nemo/actions/pulsar.nemo_action
'';

desktopItems = [
(makeDesktopItem {
name = "Pulsar";
desktopName = "Pulsar";
exec = "pulsar";
icon = "pulsar";
comment = "A Community-led Hyper-Hackable Text Editor";
genericName = "Text Editor";
categories = [ "Development" "TextEditor" "Utility" ];
mimeTypes = [ "text/plain" ];
})
];

passthru.updateScript = ./update.mjs;
mkg20001 marked this conversation as resolved.
Show resolved Hide resolved

meta = with lib; {
description = "A Community-led Hyper-Hackable Text Editor";
longDescription = ''
A Community-led Hyper-Hackable Text Editor, Forked from Atom, built on Electron.
Designed to be deeply customizable, but still approachable using the default configuration.
'';
homepage = "https://github.com/pulsar-edit/pulsar";
sourceProvenance = with sourceTypes; [ binaryNativeCode ];
license = licenses.mit;
platforms = platforms.linux;
maintainers = with maintainers; [ colamaroro ];
};
}
9 changes: 9 additions & 0 deletions pkgs/applications/editors/pulsar/pulsar.nemo_action
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Nemo Action]
Active=true
Name=Open in Pulsar
Comment=Open in Pulsar
#%U is the current selected file, this will also work on current directory
Exec=pulsar -n %U
Icon-Name=pulsar
Selection=any
Extensions=any
89 changes: 89 additions & 0 deletions pkgs/applications/editors/pulsar/update.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env nix-shell
/*
#!nix-shell -i node -p nodejs-18_x
*/

import { promises as fs } from 'node:fs';
import { promisify } from 'node:util';
import { exec as _exec } from 'node:child_process';
const exec = promisify(_exec);

const constants = {
githubUrl: "https://api.github.com/repos/pulsar-edit/pulsar/releases",
sha256FileURL: (newVersion) => `https://github.com/pulsar-edit/pulsar/releases/download/v${newVersion}/SHA256SUMS.txt`,
x86_64FileName: (newVersion) => `Linux.pulsar-${newVersion}.tar.gz`,
aarch64FileName: (newVersion) => `ARM.Linux.pulsar-${newVersion}-arm64.tar.gz`,
};

async function getLatestVersion() {
const requestResult = await fetch(constants.githubUrl);
if (!requestResult.ok) {
console.error("Failed to fetch releases");
console.error(requestResult);
process.exit(1);
};
let jsonResult = await requestResult.json();

jsonResult = jsonResult.filter((release) => !release.prerelease && !release.draft);
if (jsonResult.length == 0) {
console.error("No releases found");
process.exit(1);
}

return jsonResult[0].tag_name.replace(/^v/, '');
}

async function getSha256Sum(hashFileContent, targetFile) {
// The upstream file has a fomat like this:
// 0000000000000000000000000000000000000000000000000000000000000000 targetFile

let sha256 = hashFileContent.
split('\n').
filter((line) => line.endsWith(targetFile))[0].
split(' ')[0];

return "sha256-" + Buffer.from(sha256, 'hex').toString('base64');
}

async function getSha256Sums(newVersion) {
// Upstream provides a file with the hashes of the files, but it's not in the SRI format, and it refers to the compressed tarball
COLAMAroro marked this conversation as resolved.
Show resolved Hide resolved
// So let's just use nix-prefetch-url to get the hashes of the decompressed tarball, and `nix hash to-sri` to convert them to SRI format
const hashFileUrl = constants.sha256FileURL(newVersion);
const hashFileContent = await fetch(hashFileUrl).then((response) => response.text());

let x86_64;
let aarch64;
console.log("Getting new hashes");
let promises = [
getSha256Sum(hashFileContent, constants.x86_64FileName(newVersion)).then((hash) => { x86_64 = hash; }),
getSha256Sum(hashFileContent, constants.aarch64FileName(newVersion)).then((hash) => { aarch64 = hash; }),
];
await Promise.all(promises);
return { x86_64, aarch64 };
}

async function updateFile(newVersion, sha256Sums, currentFile) {
// There is some assumptions in how the file is formatted, but nothing egregious

let newFile = currentFile.replace(/version = "(.*)";/, `version = "${newVersion}";`);
newFile = newFile.replace(/x86_64-linux\.hash = "(.*)";/, `x86_64-linux.hash = "${sha256Sums.x86_64}";`);
newFile = newFile.replace(/aarch64-linux\.hash = "(.*)";/, `aarch64-linux.hash = "${sha256Sums.aarch64}";`);

await fs.writeFile('default.nix', newFile);
};

let currentFile = await fs.readFile('default.nix', 'utf8');
let currentVersion = currentFile.match(/version = "(.*)";/)[1];
const newVersion = await getLatestVersion();
if (currentVersion === newVersion) {
console.error("Already up to date");
process.exit(0);
}
console.log("New version: " + newVersion);
const sha256Sums = await getSha256Sums(newVersion);
console.log(sha256Sums)
if (!sha256Sums.x86_64 || !sha256Sums.aarch64) {
console.error("Failed to find sha256 sums for the 2 files");
process.exit(1);
}
updateFile(newVersion, sha256Sums, currentFile);
2 changes: 2 additions & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -28645,6 +28645,8 @@ with pkgs;

inherit (atomPackages) atom atom-beta;

pulsar = callPackage ../applications/editors/pulsar { };

asap = callPackage ../tools/audio/asap { };

aseprite = callPackage ../applications/editors/aseprite { };
Expand Down