Merge pull request #59189 from bendlas/emacs-updater-elisp
emacs-modes: replace melpa-generated with json format + updater in emacs lisp
This commit is contained in:
commit
e624d0e471
90
pkgs/applications/editors/emacs-modes/libgenerated.nix
Normal file
90
pkgs/applications/editors/emacs-modes/libgenerated.nix
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
lib: self:
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
fetcherGenerators = { repo ? null
|
||||||
|
, url ? null
|
||||||
|
, ... }:
|
||||||
|
{ sha256
|
||||||
|
, commit
|
||||||
|
, ...}: {
|
||||||
|
github = self.callPackage ({ fetchFromGitHub }:
|
||||||
|
fetchFromGitHub {
|
||||||
|
owner = lib.head (lib.splitString "/" repo);
|
||||||
|
repo = lib.head (lib.tail (lib.splitString "/" repo));
|
||||||
|
rev = commit;
|
||||||
|
inherit sha256;
|
||||||
|
}
|
||||||
|
) {};
|
||||||
|
gitlab = self.callPackage ({ fetchFromGitLab }:
|
||||||
|
fetchFromGitLab {
|
||||||
|
owner = lib.head (lib.splitString "/" repo);
|
||||||
|
repo = lib.head (lib.tail (lib.splitString "/" repo));
|
||||||
|
rev = commit;
|
||||||
|
inherit sha256;
|
||||||
|
}
|
||||||
|
) {};
|
||||||
|
git = self.callPackage ({ fetchgit }:
|
||||||
|
fetchgit {
|
||||||
|
rev = commit;
|
||||||
|
inherit sha256 url;
|
||||||
|
}
|
||||||
|
) {};
|
||||||
|
bitbucket = self.callPackage ({ fetchhg }:
|
||||||
|
fetchhg {
|
||||||
|
rev = commit;
|
||||||
|
url = "https://bitbucket.com/${repo}";
|
||||||
|
inherit sha256;
|
||||||
|
}
|
||||||
|
) {};
|
||||||
|
hg = self.callPackage ({ fetchhg }:
|
||||||
|
fetchhg {
|
||||||
|
rev = commit;
|
||||||
|
inherit sha256 url;
|
||||||
|
}
|
||||||
|
) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
|
||||||
|
melpaDerivation = variant:
|
||||||
|
{ ename, fetcher
|
||||||
|
, commit ? null
|
||||||
|
, sha256 ? null
|
||||||
|
, ... }@args:
|
||||||
|
let
|
||||||
|
sourceArgs = args."${variant}";
|
||||||
|
version = sourceArgs.version or null;
|
||||||
|
deps = sourceArgs.deps or null;
|
||||||
|
error = sourceArgs.error or args.error or null;
|
||||||
|
hasSource = lib.hasAttr variant args;
|
||||||
|
pname = builtins.replaceStrings [ "@" ] [ "at" ] ename;
|
||||||
|
broken = ! isNull error;
|
||||||
|
in
|
||||||
|
lib.nameValuePair ename (if hasSource then (
|
||||||
|
self.callPackage ({ melpaBuild, fetchurl, ... }@pkgargs:
|
||||||
|
melpaBuild {
|
||||||
|
inherit pname;
|
||||||
|
ename = ename;
|
||||||
|
version = if isNull version then "" else
|
||||||
|
lib.concatStringsSep "." (map toString version);
|
||||||
|
# TODO: Broken should not result in src being null (hack to avoid eval errors)
|
||||||
|
src = if (isNull sha256 || broken) then null else
|
||||||
|
lib.getAttr fetcher (fetcherGenerators args sourceArgs);
|
||||||
|
recipe = if isNull commit then null else
|
||||||
|
fetchurl {
|
||||||
|
name = pname + "-recipe";
|
||||||
|
url = "https://raw.githubusercontent.com/melpa/melpa/${commit}/recipes/${ename}";
|
||||||
|
inherit sha256;
|
||||||
|
};
|
||||||
|
packageRequires = lib.optional (! isNull deps)
|
||||||
|
(map (dep: pkgargs."${dep}" or self."${dep}" or null)
|
||||||
|
deps);
|
||||||
|
meta = (sourceArgs.meta or {}) // {
|
||||||
|
inherit broken;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) {}
|
||||||
|
) else null);
|
||||||
|
|
||||||
|
}
|
111400
pkgs/applications/editors/emacs-modes/melpa-generated.nix
generated
111400
pkgs/applications/editors/emacs-modes/melpa-generated.nix
generated
File diff suppressed because it is too large
Load diff
|
@ -4,12 +4,11 @@
|
||||||
|
|
||||||
To update the list of packages from MELPA,
|
To update the list of packages from MELPA,
|
||||||
|
|
||||||
1. Clone https://github.com/ttuegel/emacs2nix.
|
1. Run ./update-melpa
|
||||||
2. Clone https://github.com/milkypostman/melpa.
|
2. Check for evaluation errors:
|
||||||
3. Run `./melpa-packages.sh --melpa PATH_TO_MELPA_CLONE` from emacs2nix.
|
env NIXPKGS_ALLOW_BROKEN=1 nix-instantiate --show-trace ../../../../ -A emacsPackagesNg.melpaStablePackages
|
||||||
4. Copy the new `melpa-generated.nix` file into Nixpkgs.
|
env NIXPKGS_ALLOW_BROKEN=1 nix-instantiate --show-trace ../../../../ -A emacsPackagesNg.melpaPackages
|
||||||
5. Check for evaluation errors: `nix-instantiate ./. -A emacsPackagesNg.melpaPackages`.
|
3. `git commit -m "melpa-packages: $(date -Idate)" recipes-archive-melpa.json`
|
||||||
6. `git add pkgs/applications/editors/emacs-modes/melpa-generated.nix && git commit -m "melpa-packages $(date -Idate)"`
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -18,7 +17,9 @@ To update the list of packages from MELPA,
|
||||||
self:
|
self:
|
||||||
|
|
||||||
let
|
let
|
||||||
imported = import ./melpa-generated.nix { inherit (self) callPackage; };
|
inherit (import ./libgenerated.nix lib self) melpaDerivation;
|
||||||
|
imported = lib.listToAttrs (map (melpaDerivation "unstable")
|
||||||
|
(lib.importJSON ./recipes-archive-melpa.json));
|
||||||
super = builtins.removeAttrs imported [
|
super = builtins.removeAttrs imported [
|
||||||
"swbuff-x" # required dependency swbuff is missing
|
"swbuff-x" # required dependency swbuff is missing
|
||||||
];
|
];
|
||||||
|
@ -264,6 +265,29 @@ self:
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
# Map legacy renames from emacs2nix since code generation was ported to emacs lisp
|
||||||
|
_0blayout = super."0blayout";
|
||||||
|
_0xc = super."0xc";
|
||||||
|
_2048-game = super."2048-game";
|
||||||
|
_4clojure = super."4clojure";
|
||||||
|
at = super."@";
|
||||||
|
desktop-plus = super."desktop+";
|
||||||
|
# filesets-plus = super."filesets+";
|
||||||
|
ghub-plus = super."ghub+";
|
||||||
|
git-gutter-plus = super."git-gutter+";
|
||||||
|
git-gutter-fringe-plus = super."git-gutter-fringe+";
|
||||||
|
ido-completing-read-plus = super."ido-completing-read+";
|
||||||
|
image-plus = super."image+";
|
||||||
|
image-dired-plus = super."image-dired+";
|
||||||
|
markdown-mode-plus = super."markdown-mode+";
|
||||||
|
package-plus = super."package+";
|
||||||
|
rect-plus = super."rect+";
|
||||||
|
term-plus = super."term+";
|
||||||
|
term-plus-key-intercept = super."term+key-intercept";
|
||||||
|
term-plus-mux = super."term+mux";
|
||||||
|
xml-plus = super."xml+";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
melpaPackages =
|
melpaPackages =
|
||||||
|
|
56691
pkgs/applications/editors/emacs-modes/melpa-stable-generated.nix
generated
56691
pkgs/applications/editors/emacs-modes/melpa-stable-generated.nix
generated
File diff suppressed because it is too large
Load diff
|
@ -4,22 +4,23 @@
|
||||||
|
|
||||||
To update the list of packages from MELPA,
|
To update the list of packages from MELPA,
|
||||||
|
|
||||||
1. Clone https://github.com/ttuegel/emacs2nix.
|
|
||||||
2. Clone https://github.com/milkypostman/melpa.
|
1. Run ./update-melpa
|
||||||
3. Run `./melpa-stable-packages.sh --melpa PATH_TO_MELPA_CLONE` from emacs2nix.
|
2. Check for evaluation errors:
|
||||||
4. Copy the new `melpa-stable-generated.nix` file into Nixpkgs.
|
env NIXPKGS_ALLOW_BROKEN=1 nix-instantiate --show-trace ../../../../ -A emacsPackagesNg.melpaStablePackages
|
||||||
5. Check for evaluation errors: `nix-instantiate ./. -A emacsPackagesNg.melpaStablePackages`.
|
env NIXPKGS_ALLOW_BROKEN=1 nix-instantiate --show-trace ../../../../ -A emacsPackagesNg.melpaPackages
|
||||||
6. `git add pkgs/applications/editors/emacs-modes/melpa-stable-generated.nix && git commit -m "melpa-stable-packages $(date -Idate)"`
|
3. `git commit -m "melpa-packages: $(date -Idate)" recipes-archive-melpa.json`
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{ external }:
|
{ lib, external }:
|
||||||
|
|
||||||
self:
|
self:
|
||||||
|
|
||||||
let
|
let
|
||||||
imported = import ./melpa-stable-generated.nix { inherit (self) callPackage; };
|
inherit (import ./libgenerated.nix lib self) melpaDerivation;
|
||||||
|
imported = lib.listToAttrs (map (melpaDerivation "stable")
|
||||||
|
(lib.importJSON ./recipes-archive-melpa.json));
|
||||||
super = imported;
|
super = imported;
|
||||||
|
|
||||||
dontConfigure = pkg: pkg.override (args: {
|
dontConfigure = pkg: pkg.override (args: {
|
||||||
|
@ -28,11 +29,11 @@ self:
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
markBroken = pkg: pkg.override (args: {
|
markBroken = pkg: if pkg != null then pkg.override (args: {
|
||||||
melpaBuild = drv: args.melpaBuild (drv // {
|
melpaBuild = drv: args.melpaBuild (drv // {
|
||||||
meta = (drv.meta or {}) // { broken = true; };
|
meta = (drv.meta or {}) // { broken = true; };
|
||||||
});
|
});
|
||||||
});
|
}) else null;
|
||||||
|
|
||||||
overrides = {
|
overrides = {
|
||||||
# Expects bash to be at /bin/bash
|
# Expects bash to be at /bin/bash
|
||||||
|
@ -205,6 +206,28 @@ self:
|
||||||
|
|
||||||
# upstream issue: missing file header
|
# upstream issue: missing file header
|
||||||
window-numbering = markBroken super.window-numbering;
|
window-numbering = markBroken super.window-numbering;
|
||||||
|
|
||||||
|
# Map legacy renames from emacs2nix since code generation was ported to emacs lisp
|
||||||
|
_0blayout = super."0blayout";
|
||||||
|
_0xc = super."0xc";
|
||||||
|
_2048-game = super."2048-game";
|
||||||
|
_4clojure = super."4clojure";
|
||||||
|
at = super."@";
|
||||||
|
desktop-plus = super."desktop+";
|
||||||
|
ghub-plus = super."ghub+";
|
||||||
|
git-gutter-plus = super."git-gutter+";
|
||||||
|
git-gutter-fringe-plus = super."git-gutter-fringe+";
|
||||||
|
ido-completing-read-plus = super."ido-completing-read+";
|
||||||
|
image-plus = super."image+";
|
||||||
|
image-dired-plus = super."image-dired+";
|
||||||
|
markdown-mode-plus = super."markdown-mode+";
|
||||||
|
package-plus = super."package+";
|
||||||
|
rect-plus = super."rect+";
|
||||||
|
term-plus = super."term+";
|
||||||
|
term-plus-key-intercept = super."term+key-intercept";
|
||||||
|
term-plus-mux = super."term+mux";
|
||||||
|
xml-plus = super."xml+";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
melpaStablePackages = super // overrides;
|
melpaStablePackages = super // overrides;
|
||||||
|
|
96458
pkgs/applications/editors/emacs-modes/recipes-archive-melpa.json
Normal file
96458
pkgs/applications/editors/emacs-modes/recipes-archive-melpa.json
Normal file
File diff suppressed because it is too large
Load diff
8
pkgs/applications/editors/emacs-modes/update-melpa
Executable file
8
pkgs/applications/editors/emacs-modes/update-melpa
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#! /usr/bin/env nix-shell
|
||||||
|
#! nix-shell --show-trace -i sh -p git nix nix-prefetch-git nix-prefetch-hg "import ./updater-emacs.nix"
|
||||||
|
|
||||||
|
# "with import ../../../.. {}; emacsWithPackages (epkgs: with epkgs.melpaPackages; [ promise semaphore ])"
|
||||||
|
|
||||||
|
exec emacs --fg-daemon=updater --quick -l update-melpa.el -f run-updater "$@"
|
||||||
|
|
||||||
|
# exec emacs update-melpa.el "$@"
|
434
pkgs/applications/editors/emacs-modes/update-melpa.el
Normal file
434
pkgs/applications/editors/emacs-modes/update-melpa.el
Normal file
|
@ -0,0 +1,434 @@
|
||||||
|
;; -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; This is the updater for recipes-archive-melpa.json
|
||||||
|
|
||||||
|
(require 'promise)
|
||||||
|
(require 'semaphore-promise)
|
||||||
|
(require 'url)
|
||||||
|
(require 'json)
|
||||||
|
(require 'cl)
|
||||||
|
(require 'subr-x)
|
||||||
|
(require 'seq)
|
||||||
|
|
||||||
|
;; # Lib
|
||||||
|
|
||||||
|
(defun alist-set (key value alist)
|
||||||
|
(cons
|
||||||
|
(cons key value)
|
||||||
|
(assq-delete-all
|
||||||
|
key alist)))
|
||||||
|
|
||||||
|
(defun alist-update (key f alist)
|
||||||
|
(let ((value (alist-get key alist)))
|
||||||
|
(cons
|
||||||
|
(cons key (funcall f value))
|
||||||
|
(assq-delete-all
|
||||||
|
key alist))))
|
||||||
|
|
||||||
|
|
||||||
|
(defun process-promise (semaphore program &rest args)
|
||||||
|
"Generate an asynchronous process and
|
||||||
|
return Promise to resolve in that process."
|
||||||
|
(promise-then
|
||||||
|
(semaphore-promise-gated
|
||||||
|
semaphore
|
||||||
|
(lambda (resolve reject)
|
||||||
|
(funcall resolve (apply #'promise:make-process program args))))
|
||||||
|
#'car))
|
||||||
|
|
||||||
|
(defun mangle-name (s)
|
||||||
|
(if (string-match "^[a-zA-Z].*" s)
|
||||||
|
s
|
||||||
|
(concat "_" s)))
|
||||||
|
|
||||||
|
;; ## Shell promise + env
|
||||||
|
|
||||||
|
(defun as-string (o)
|
||||||
|
(with-output-to-string (princ o)))
|
||||||
|
|
||||||
|
(defun assocenv (env &rest namevals)
|
||||||
|
(let ((process-environment (copy-sequence env)))
|
||||||
|
(mapc (lambda (e)
|
||||||
|
(setenv (as-string (car e))
|
||||||
|
(cadr e)))
|
||||||
|
(seq-partition namevals 2))
|
||||||
|
process-environment))
|
||||||
|
|
||||||
|
(defun shell-promise (semaphore env script)
|
||||||
|
(semaphore-promise-gated
|
||||||
|
semaphore
|
||||||
|
(lambda (resolve reject)
|
||||||
|
(let ((process-environment env))
|
||||||
|
(funcall resolve (promise:make-shell-command script))))))
|
||||||
|
|
||||||
|
;; # Updater
|
||||||
|
|
||||||
|
;; ## Previous Archive Reader
|
||||||
|
|
||||||
|
(defun previous-commit (index ename variant)
|
||||||
|
(when-let (pdesc (and index (gethash ename index)))
|
||||||
|
(when-let (desc (and pdesc (gethash variant pdesc)))
|
||||||
|
(gethash 'commit desc))))
|
||||||
|
|
||||||
|
(defun previous-sha256 (index ename variant)
|
||||||
|
(when-let (pdesc (and index (gethash ename index)))
|
||||||
|
(when-let (desc (and pdesc (gethash variant pdesc)))
|
||||||
|
(gethash 'sha256 desc))))
|
||||||
|
|
||||||
|
(defun parse-previous-archive (filename)
|
||||||
|
(let ((idx (make-hash-table :test 'equal)))
|
||||||
|
(loop for desc in
|
||||||
|
(let ((json-object-type 'hash-table)
|
||||||
|
(json-array-type 'list)
|
||||||
|
(json-key-type 'symbol))
|
||||||
|
(json-read-file filename))
|
||||||
|
do (puthash (gethash 'ename desc)
|
||||||
|
desc idx))
|
||||||
|
idx))
|
||||||
|
|
||||||
|
;; ## Prefetcher
|
||||||
|
|
||||||
|
;; (defun latest-git-revision (url)
|
||||||
|
;; (process-promise "git" "ls-remote" url))
|
||||||
|
|
||||||
|
(defun prefetch (semaphore fetcher repo commit)
|
||||||
|
(promise-then
|
||||||
|
(apply 'process-promise
|
||||||
|
semaphore
|
||||||
|
(pcase fetcher
|
||||||
|
("github" (list "nix-prefetch-url"
|
||||||
|
"--unpack" (concat "https://github.com/" repo "/archive/" commit ".tar.gz")))
|
||||||
|
("gitlab" (list "nix-prefetch-url"
|
||||||
|
"--unpack" (concat "https://gitlab.com/" repo "/repository/archive.tar.gz?ref=" commit)))
|
||||||
|
("bitbucket" (list "nix-prefetch-hg"
|
||||||
|
(concat "https://bitbucket.com/" repo) commit))
|
||||||
|
("hg" (list "nix-prefetch-hg"
|
||||||
|
repo commit))
|
||||||
|
("git" (list "nix-prefetch-git"
|
||||||
|
"--fetch-submodules"
|
||||||
|
"--url" repo
|
||||||
|
"--rev" commit))
|
||||||
|
(_ (throw 'unknown-fetcher fetcher))))
|
||||||
|
(lambda (res)
|
||||||
|
(pcase fetcher
|
||||||
|
("git" (alist-get 'sha256 (json-read-from-string res)))
|
||||||
|
(_ (car (split-string res)))))))
|
||||||
|
|
||||||
|
(defun source-sha (semaphore ename eprops aprops previous variant)
|
||||||
|
(let* ((fetcher (alist-get 'fetcher eprops))
|
||||||
|
(url (alist-get 'url eprops))
|
||||||
|
(repo (alist-get 'repo eprops))
|
||||||
|
(commit (gethash 'commit aprops))
|
||||||
|
(prev-commit (previous-commit previous ename variant))
|
||||||
|
(prev-sha256 (previous-sha256 previous ename variant)))
|
||||||
|
(if (and commit prev-sha256
|
||||||
|
(equal prev-commit commit))
|
||||||
|
(progn
|
||||||
|
(message "INFO: %s: re-using %s %s" ename prev-commit prev-sha256)
|
||||||
|
(promise-resolve `((sha256 . ,prev-sha256))))
|
||||||
|
(if (and commit (or repo url))
|
||||||
|
(promise-then
|
||||||
|
(prefetch semaphore fetcher (or repo url) commit)
|
||||||
|
(lambda (sha256)
|
||||||
|
(message "INFO: %s: prefetched repository %s %s" ename commit sha256)
|
||||||
|
`((sha256 . ,sha256)))
|
||||||
|
(lambda (err)
|
||||||
|
(message "ERROR: %s: during prefetch %s" ename err)
|
||||||
|
(promise-resolve
|
||||||
|
`((error . ,err)))))
|
||||||
|
(progn
|
||||||
|
(message "ERROR: %s: no commit information" ename)
|
||||||
|
(promise-resolve
|
||||||
|
`((error . "No commit information"))))))))
|
||||||
|
|
||||||
|
(defun source-info (recipe archive source-sha)
|
||||||
|
(let* ((esym (car recipe))
|
||||||
|
(ename (symbol-name esym))
|
||||||
|
(eprops (cdr recipe))
|
||||||
|
(aentry (gethash esym archive))
|
||||||
|
(version (and aentry (gethash 'ver aentry)))
|
||||||
|
(deps (when-let (deps (gethash 'deps aentry))
|
||||||
|
(remove 'emacs (hash-table-keys deps))))
|
||||||
|
(aprops (and aentry (gethash 'props aentry)))
|
||||||
|
(commit (gethash 'commit aprops)))
|
||||||
|
(append `((version . ,version))
|
||||||
|
(when (< 0 (length deps))
|
||||||
|
`((deps . ,(sort deps 'string<))))
|
||||||
|
`((commit . ,commit))
|
||||||
|
source-sha)))
|
||||||
|
|
||||||
|
(defun recipe-info (recipe-index ename)
|
||||||
|
(if-let (desc (gethash ename recipe-index))
|
||||||
|
(destructuring-bind (rcp-commit . rcp-sha256) desc
|
||||||
|
`((commit . ,rcp-commit)
|
||||||
|
(sha256 . ,rcp-sha256)))
|
||||||
|
`((error . "No recipe info"))))
|
||||||
|
|
||||||
|
(defun start-fetch (semaphore recipe-index-promise recipes unstable-archive stable-archive previous)
|
||||||
|
(promise-all
|
||||||
|
(mapcar (lambda (entry)
|
||||||
|
(let* ((esym (car entry))
|
||||||
|
(ename (symbol-name esym))
|
||||||
|
(eprops (cdr entry))
|
||||||
|
(fetcher (alist-get 'fetcher eprops))
|
||||||
|
(url (alist-get 'url eprops))
|
||||||
|
(repo (alist-get 'repo eprops))
|
||||||
|
|
||||||
|
(unstable-aentry (gethash esym unstable-archive))
|
||||||
|
(unstable-aprops (and unstable-aentry (gethash 'props unstable-aentry)))
|
||||||
|
(unstable-commit (and unstable-aprops (gethash 'commit unstable-aprops)))
|
||||||
|
|
||||||
|
(stable-aentry (gethash esym stable-archive))
|
||||||
|
(stable-aprops (and stable-aentry (gethash 'props stable-aentry)))
|
||||||
|
(stable-commit (and stable-aprops (gethash 'commit stable-aprops)))
|
||||||
|
|
||||||
|
(unstable-shap (if unstable-aprops
|
||||||
|
(source-sha semaphore ename eprops unstable-aprops previous 'unstable)
|
||||||
|
(promise-resolve nil)))
|
||||||
|
(stable-shap (if (equal unstable-commit stable-commit)
|
||||||
|
unstable-shap
|
||||||
|
(if stable-aprops
|
||||||
|
(source-sha semaphore ename eprops stable-aprops previous 'stable)
|
||||||
|
(promise-resolve nil)))))
|
||||||
|
|
||||||
|
(promise-then
|
||||||
|
(promise-all (list recipe-index-promise unstable-shap stable-shap))
|
||||||
|
(lambda (res)
|
||||||
|
(seq-let [recipe-index unstable-sha stable-sha] res
|
||||||
|
(append `((ename . ,ename))
|
||||||
|
(if-let (desc (gethash ename recipe-index))
|
||||||
|
(destructuring-bind (rcp-commit . rcp-sha256) desc
|
||||||
|
(append `((commit . ,rcp-commit)
|
||||||
|
(sha256 . ,rcp-sha256))
|
||||||
|
(when (not unstable-aprops)
|
||||||
|
(message "ERROR: %s: not in archive" ename)
|
||||||
|
`((error . "Not in archive")))))
|
||||||
|
`((error . "No recipe info")))
|
||||||
|
`((fetcher . ,fetcher))
|
||||||
|
(if (or (equal "github" fetcher)
|
||||||
|
(equal "bitbucket" fetcher)
|
||||||
|
(equal "gitlab" fetcher))
|
||||||
|
`((repo . ,repo))
|
||||||
|
`((url . ,url)))
|
||||||
|
(when unstable-aprops `((unstable . ,(source-info entry unstable-archive unstable-sha))))
|
||||||
|
(when stable-aprops `((stable . ,(source-info entry stable-archive stable-sha))))))))))
|
||||||
|
recipes)))
|
||||||
|
|
||||||
|
;; ## Emitter
|
||||||
|
|
||||||
|
(defun emit-json (prefetch-semaphore recipe-index-promise recipes archive stable-archive previous)
|
||||||
|
(promise-then
|
||||||
|
(start-fetch
|
||||||
|
prefetch-semaphore
|
||||||
|
recipe-index-promise
|
||||||
|
(sort recipes (lambda (a b)
|
||||||
|
(string-lessp
|
||||||
|
(symbol-name (car a))
|
||||||
|
(symbol-name (car b)))))
|
||||||
|
archive stable-archive
|
||||||
|
previous)
|
||||||
|
(lambda (descriptors)
|
||||||
|
(message "Finished downloading %d descriptors" (length descriptors))
|
||||||
|
(let ((buf (generate-new-buffer "*recipes-archive*")))
|
||||||
|
(with-current-buffer buf
|
||||||
|
;; (switch-to-buffer buf)
|
||||||
|
;; (json-mode)
|
||||||
|
(insert
|
||||||
|
(let ((json-encoding-pretty-print t)
|
||||||
|
(json-encoding-default-indentation " "))
|
||||||
|
(json-encode descriptors)))
|
||||||
|
buf)))))
|
||||||
|
|
||||||
|
;; ## Recipe indexer
|
||||||
|
|
||||||
|
(defun http-get (url parser)
|
||||||
|
(promise-new
|
||||||
|
(lambda (resolve reject)
|
||||||
|
(url-retrieve
|
||||||
|
url (lambda (status)
|
||||||
|
(funcall resolve (condition-case err
|
||||||
|
(progn
|
||||||
|
(goto-char (point-min))
|
||||||
|
(search-forward "\n\n")
|
||||||
|
(message (buffer-substring (point-min) (point)))
|
||||||
|
(delete-region (point-min) (point))
|
||||||
|
(funcall parser))
|
||||||
|
(funcall reject err))))))))
|
||||||
|
|
||||||
|
(defun json-read-buffer (buffer)
|
||||||
|
(with-current-buffer buffer
|
||||||
|
(save-excursion
|
||||||
|
(mark-whole-buffer)
|
||||||
|
(json-read))))
|
||||||
|
|
||||||
|
(defun error-count (recipes-archive)
|
||||||
|
(length
|
||||||
|
(seq-filter
|
||||||
|
(lambda (desc)
|
||||||
|
(alist-get 'error desc))
|
||||||
|
recipes-archive)))
|
||||||
|
|
||||||
|
;; (error-count (json-read-buffer "recipes-archive-melpa.json"))
|
||||||
|
|
||||||
|
(defun latest-recipe-commit (semaphore repo base-rev recipe)
|
||||||
|
(shell-promise
|
||||||
|
semaphore (assocenv process-environment
|
||||||
|
"GIT_DIR" repo
|
||||||
|
"BASE_REV" base-rev
|
||||||
|
"RECIPE" recipe)
|
||||||
|
"exec git log --first-parent -n1 --pretty=format:%H $BASE_REV -- recipes/$RECIPE"))
|
||||||
|
|
||||||
|
(defun latest-recipe-sha256 (semaphore repo base-rev recipe)
|
||||||
|
(promise-then
|
||||||
|
(shell-promise
|
||||||
|
semaphore (assocenv process-environment
|
||||||
|
"GIT_DIR" repo
|
||||||
|
"BASE_REV" base-rev
|
||||||
|
"RECIPE" recipe)
|
||||||
|
"exec nix-hash --flat --type sha256 --base32 <(
|
||||||
|
git cat-file blob $(
|
||||||
|
git ls-tree $BASE_REV recipes/$RECIPE | cut -f1 | cut -d' ' -f3
|
||||||
|
)
|
||||||
|
)")
|
||||||
|
(lambda (res)
|
||||||
|
(car
|
||||||
|
(split-string res)))))
|
||||||
|
|
||||||
|
(defun index-recipe-commits (semaphore repo base-rev recipes)
|
||||||
|
(promise-then
|
||||||
|
(promise-all
|
||||||
|
(mapcar (lambda (recipe)
|
||||||
|
(promise-then
|
||||||
|
(latest-recipe-commit semaphore repo base-rev recipe)
|
||||||
|
(let ((sha256p (latest-recipe-sha256 semaphore repo base-rev recipe)))
|
||||||
|
(lambda (commit)
|
||||||
|
(promise-then sha256p
|
||||||
|
(lambda (sha256)
|
||||||
|
(message "Indexed Recipe %s %s %s" recipe commit sha256)
|
||||||
|
(cons recipe (cons commit sha256))))))))
|
||||||
|
recipes))
|
||||||
|
(lambda (rcp-commits)
|
||||||
|
(let ((idx (make-hash-table :test 'equal)))
|
||||||
|
(mapc (lambda (rcpc)
|
||||||
|
(puthash (car rcpc) (cdr rcpc) idx))
|
||||||
|
rcp-commits)
|
||||||
|
idx))))
|
||||||
|
|
||||||
|
(defun with-melpa-checkout (resolve)
|
||||||
|
(let ((tmpdir (make-temp-file "melpa-" t)))
|
||||||
|
(promise-finally
|
||||||
|
(promise-then
|
||||||
|
(shell-promise
|
||||||
|
(semaphore-create 1 "dummy")
|
||||||
|
(assocenv process-environment "MELPA_DIR" tmpdir)
|
||||||
|
"cd $MELPA_DIR
|
||||||
|
(git init --bare
|
||||||
|
git remote add origin https://github.com/melpa/melpa.git
|
||||||
|
git fetch origin) 1>&2
|
||||||
|
echo -n $MELPA_DIR")
|
||||||
|
(lambda (dir)
|
||||||
|
(message "Created melpa checkout %s" dir)
|
||||||
|
(funcall resolve dir)))
|
||||||
|
(lambda ()
|
||||||
|
(delete-directory tmpdir t)
|
||||||
|
(message "Deleted melpa checkout %s" tmpdir)))))
|
||||||
|
|
||||||
|
(defun list-recipes (repo base-rev)
|
||||||
|
(promise-then
|
||||||
|
(shell-promise nil (assocenv process-environment
|
||||||
|
"GIT_DIR" repo
|
||||||
|
"BASE_REV" base-rev)
|
||||||
|
"git ls-tree --name-only $BASE_REV recipes/")
|
||||||
|
(lambda (s)
|
||||||
|
(mapcar (lambda (n)
|
||||||
|
(substring n 8))
|
||||||
|
(split-string s)))))
|
||||||
|
|
||||||
|
;; ## Main runner
|
||||||
|
|
||||||
|
(defvar recipe-indexp)
|
||||||
|
(defvar archivep)
|
||||||
|
|
||||||
|
(defun run-updater ()
|
||||||
|
(message "Turning off logging to *Message* buffer")
|
||||||
|
(setq message-log-max nil)
|
||||||
|
(setenv "GIT_ASKPASS")
|
||||||
|
(setenv "SSH_ASKPASS")
|
||||||
|
(setq process-adaptive-read-buffering nil)
|
||||||
|
|
||||||
|
;; Indexer and Prefetcher run in parallel
|
||||||
|
|
||||||
|
;; Recipe Indexer
|
||||||
|
(setq recipe-indexp
|
||||||
|
(with-melpa-checkout
|
||||||
|
(lambda (repo)
|
||||||
|
(promise-then
|
||||||
|
(promise-then
|
||||||
|
(list-recipes repo "origin/master")
|
||||||
|
(lambda (recipe-names)
|
||||||
|
(promise:make-thread #'index-recipe-commits
|
||||||
|
;; The indexer runs on a local git repository,
|
||||||
|
;; so it is CPU bound.
|
||||||
|
;; Adjust for core count + 2
|
||||||
|
(semaphore-create 6 "local-indexer")
|
||||||
|
repo "origin/master"
|
||||||
|
;; (seq-take recipe-names 20)
|
||||||
|
recipe-names)))
|
||||||
|
(lambda (res)
|
||||||
|
(message "Indexed Recipes: %d" (hash-table-count res))
|
||||||
|
(defvar recipe-index res)
|
||||||
|
res)
|
||||||
|
(lambda (err)
|
||||||
|
(message "ERROR: %s" err))))))
|
||||||
|
|
||||||
|
;; Prefetcher + Emitter
|
||||||
|
(setq archivep
|
||||||
|
(promise-then
|
||||||
|
(promise-then (promise-all
|
||||||
|
(list (http-get "https://melpa.org/recipes.json"
|
||||||
|
(lambda ()
|
||||||
|
(let ((json-object-type 'alist)
|
||||||
|
(json-array-type 'list)
|
||||||
|
(json-key-type 'symbol))
|
||||||
|
(json-read))))
|
||||||
|
(http-get "https://melpa.org/archive.json"
|
||||||
|
(lambda ()
|
||||||
|
(let ((json-object-type 'hash-table)
|
||||||
|
(json-array-type 'list)
|
||||||
|
(json-key-type 'symbol))
|
||||||
|
(json-read))))
|
||||||
|
(http-get "https://stable.melpa.org/archive.json"
|
||||||
|
(lambda ()
|
||||||
|
(let ((json-object-type 'hash-table)
|
||||||
|
(json-array-type 'list)
|
||||||
|
(json-key-type 'symbol))
|
||||||
|
(json-read))))))
|
||||||
|
(lambda (resolved)
|
||||||
|
(message "Finished download")
|
||||||
|
(seq-let [recipes-content archive-content stable-archive-content] resolved
|
||||||
|
;; The prefetcher is network bound, so 64 seems a good estimate
|
||||||
|
;; for parallel network connections
|
||||||
|
(promise:make-thread #'emit-json (semaphore-create 64 "prefetch-pool")
|
||||||
|
recipe-indexp
|
||||||
|
recipes-content
|
||||||
|
archive-content
|
||||||
|
stable-archive-content
|
||||||
|
(parse-previous-archive "recipes-archive-melpa.json")))))
|
||||||
|
(lambda (buf)
|
||||||
|
(with-current-buffer buf
|
||||||
|
(write-file "recipes-archive-melpa.json")))
|
||||||
|
(lambda (err)
|
||||||
|
(message "ERROR: %s" err))))
|
||||||
|
|
||||||
|
;; Shutdown routine
|
||||||
|
(make-thread
|
||||||
|
(lambda ()
|
||||||
|
(promise-finally archivep
|
||||||
|
(lambda ()
|
||||||
|
;; (message "Joining threads %s" (all-threads))
|
||||||
|
;; (mapc (lambda (thr)
|
||||||
|
;; (when (not (eq thr (current-thread)))
|
||||||
|
;; (thread-join thr)))
|
||||||
|
;; (all-threads))
|
||||||
|
|
||||||
|
(kill-emacs 0))))))
|
29
pkgs/applications/editors/emacs-modes/updater-emacs.nix
Normal file
29
pkgs/applications/editors/emacs-modes/updater-emacs.nix
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
with import ../../../.. {};
|
||||||
|
(emacsPackagesNgFor emacs26).
|
||||||
|
emacsWithPackages (epkgs: let
|
||||||
|
promise = epkgs.trivialBuild {
|
||||||
|
pname = "promise";
|
||||||
|
version = "1";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "bendlas";
|
||||||
|
repo = "emacs-promise";
|
||||||
|
rev = "4da97087c5babbd8429b5ce62a8323b9b03c6022";
|
||||||
|
sha256 = "0yin7kj69g4zxs30pvk47cnfygxlaw7jc7chr3b36lz51yqczjsy";
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
semaphore = epkgs.trivialBuild {
|
||||||
|
pname = "semaphore";
|
||||||
|
version = "1";
|
||||||
|
packageRequires = [ promise ];
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "webnf";
|
||||||
|
repo = "semaphore.el";
|
||||||
|
rev = "93802cb093073bc6a6ccd797328dafffcef248e0";
|
||||||
|
sha256 = "09pfyp27m35sv340xarhld7xx2vv5fs5xj4418709iw6l6hpk853";
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in [ promise semaphore ]
|
||||||
|
# ++ (with epkgs.melpaPackages; [ smex rainbow-delimiters paredit ])
|
||||||
|
)
|
|
@ -50,7 +50,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
melpaStablePackages = import ../applications/editors/emacs-modes/melpa-stable-packages.nix {
|
melpaStablePackages = import ../applications/editors/emacs-modes/melpa-stable-packages.nix {
|
||||||
inherit external;
|
inherit external lib;
|
||||||
};
|
};
|
||||||
|
|
||||||
melpaPackages = import ../applications/editors/emacs-modes/melpa-packages.nix {
|
melpaPackages = import ../applications/editors/emacs-modes/melpa-packages.nix {
|
||||||
|
|
Loading…
Reference in a new issue