Skip to content

Commit d7ca9f8

Browse files
committed
feat(install): Add commands install-file and install-vc
1 parent c49f53c commit d7ca9f8

File tree

19 files changed

+437
-64
lines changed

19 files changed

+437
-64
lines changed

cmds/core/install-file.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (C) 2025 the Eask authors.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 3, or (at your option)
7+
* any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
"use strict";
19+
20+
exports.command = ['install-file [files..]'];
21+
exports.desc = 'Install packages from files, .tar files, or directories';
22+
exports.builder = yargs => yargs
23+
.positional(
24+
'[files..]', {
25+
description: 'files to install as packages',
26+
type: 'array',
27+
});
28+
29+
exports.handler = async (argv) => {
30+
await UTIL.e_call(argv, 'core/install-file', argv.files);
31+
};

cmds/core/install-vc.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (C) 2025 the Eask authors.
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 3, or (at your option)
7+
* any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
"use strict";
19+
20+
exports.command = ['install-vc [specs..]'];
21+
exports.desc = 'Install packages directly from the version control';
22+
exports.builder = yargs => yargs
23+
.positional(
24+
'[specs..]', {
25+
description: 'vc specification to install as packages',
26+
type: 'array',
27+
});
28+
29+
exports.handler = async (argv) => {
30+
await UTIL.e_call(argv, 'core/install-vc', argv.specs);
31+
};

docs/content/DSL/_index.en.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Declare package's author.
5656

5757
## 🔍 **package-file** (`file` `version` `description`)
5858

59-
Define this package and its runtime dependencies from the package headers
59+
Define this package and its runtime dependencies from the package headers
6060
of a file (used only for package development).
6161

6262
```elisp
@@ -65,7 +65,7 @@ of a file (used only for package development).
6565

6666
## 🔍 **package-descriptor** (`pkg-file`)
6767

68-
Declare all package metadata directly by specifying a package descriptor
68+
Declare all package metadata directly by specifying a package descriptor
6969
contained in file with name given by file.
7070

7171
```elisp
@@ -149,14 +149,30 @@ Specify dependencies that are listed in **archives**:
149149
(depends-on "company")
150150
```
151151

152+
Specify dependencies in **file** format:
153+
154+
```elisp
155+
(depends-on "auto-rename-tag" :file "/path/to/auto-rename-tag")
156+
157+
(depends-on "lsp-ui" :file "/path/to/lsp-ui")
158+
```
159+
160+
Specify dependencies in **vc** format:
161+
162+
```elisp
163+
(depends-on "auto-rename-tag" :vc "jcs-elpa/auto-rename-tag")
164+
165+
(depends-on "lsp-ui" :vc "emacs-lsp/lsp-ui")
166+
```
167+
152168
Specify dependencies in **recipe** format:
153169

154170
```elisp
155-
(depends-on "auto-rename-tag"
156-
:repo "jcs-elpa/auto-rename-tag"
171+
(depends-on "auto-rename-tag"
172+
:repo "jcs-elpa/auto-rename-tag"
157173
:fetcher 'github)
158174
159-
(depends-on "lsp-ui"
175+
(depends-on "lsp-ui"
160176
:repo "emacs-lsp/lsp-ui"
161177
:fetcher 'github
162178
:files '(:defaults "lsp-ui-doc.html" "resources"))

docs/content/DSL/_index.zh-tw.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,30 @@ weight: 200
145145
(depends-on "company")
146146
```
147147

148+
**file** 格式指定依賴項:
149+
150+
```elisp
151+
(depends-on "auto-rename-tag" :file "/path/to/auto-rename-tag")
152+
153+
(depends-on "lsp-ui" :file "/path/to/lsp-ui")
154+
```
155+
156+
**vc** 格式指定依賴項:
157+
158+
```elisp
159+
(depends-on "auto-rename-tag" :vc "jcs-elpa/auto-rename-tag")
160+
161+
(depends-on "lsp-ui" :vc "emacs-lsp/lsp-ui")
162+
```
163+
148164
**recipe** 格式指定依賴項:
149165

150166
```elisp
151-
(depends-on "auto-rename-tag"
152-
:repo "jcs-elpa/auto-rename-tag"
167+
(depends-on "auto-rename-tag"
168+
:repo "jcs-elpa/auto-rename-tag"
153169
:fetcher 'github)
154170
155-
(depends-on "lsp-ui"
171+
(depends-on "lsp-ui"
156172
:repo "emacs-lsp/lsp-ui"
157173
:fetcher 'github
158174
:files '(:defaults "lsp-ui-doc.html" "resources"))

lisp/_prepare.el

Lines changed: 102 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@ will return `lint/checkdoc' with a dash between two subcommands."
152152
(list script-file))
153153
"/"))))
154154

155+
(defun eask-command-check (version)
156+
"Report error if the current command requires minimum VERSION."
157+
(when (version< emacs-version version)
158+
(eask-error "The command `%s' requires Emacs %s and above!"
159+
(eask-command) version)))
160+
155161
(defun eask-command-p (commands)
156162
"Return t if COMMANDS is the current command."
157163
(member (eask-command) (eask-listify commands)))
@@ -542,10 +548,25 @@ For arguments FUNC and DEPS, see function `mapc' for more information."
542548
(len (length deps))
543549
(fmt (eask--action-format len))
544550
(count 0))
545-
(dolist (pkg deps)
551+
(dolist (dep deps)
546552
(cl-incf count)
547553
(setq eask--action-prefix (format fmt count))
548-
(funcall func pkg))))
554+
(funcall func dep))))
555+
556+
(defun eask--install-dep (dep)
557+
"Custom install DEP."
558+
(let ((name (car dep)))
559+
(cond
560+
;; Install through the function `package-install-file'.
561+
((memq :file dep)
562+
(let ((file (nth 2 dep)))
563+
(eask-package-install-file name file)))
564+
;; Install through the function `package-vc-install'.
565+
((memq :vc dep)
566+
(let ((spec (cdr (memq :vc dep))))
567+
(eask-package-vc-install name spec)))
568+
;; Fallback to archive install.
569+
(t (eask-package-install name)))))
549570

550571
(defun eask--install-deps (dependencies msg)
551572
"Install DEPENDENCIES.
@@ -557,10 +578,11 @@ scope of the dependencies (it's either `production' or `development')."
557578
(len (length dependencies))
558579
(ies (eask--sinr len "y" "ies"))
559580
(pkg-installed (cl-remove-if #'package-installed-p names))
560-
(installed (length pkg-installed)) (skipped (- len installed)))
581+
(installed (length pkg-installed))
582+
(skipped (- len installed)))
561583
(eask-log "Installing %s %s dependenc%s..." len msg ies)
562584
(eask-msg "")
563-
(eask--package-mapc #'eask-package-install names)
585+
(eask--package-mapc #'eask--install-dep dependencies)
564586
(eask-msg "")
565587
(eask-info "(Total of %s dependenc%s installed, %s skipped)"
566588
installed ies skipped)))
@@ -669,6 +691,38 @@ Argument BODY are forms for execution."
669691
"Return non-nil if package (PKG) is installable."
670692
(assq (eask-intern pkg) package-archive-contents))
671693

694+
(defun eask-package-vc-install (pkg spec)
695+
"To vc install the package (PKG) by argument SPEC."
696+
(eask-defvc< 27 (eask-pkg-init)) ; XXX: remove this after we drop 26.x
697+
(eask--pkg-process pkg
698+
(cond
699+
((package-installed-p pkg)
700+
(eask-msg " - %sSkipping %s (%s)... already installed ✗"
701+
eask--action-prefix
702+
name version))
703+
(t
704+
(eask-with-progress
705+
(format " - %sInstalling %s (%s)... " eask--action-prefix name version)
706+
(eask-with-verbosity 'debug
707+
(apply #'package-vc-install spec))
708+
"done ✓")))))
709+
710+
(defun eask-package-install-file (pkg file)
711+
"To FILE install the package (PKG)."
712+
(eask-defvc< 27 (eask-pkg-init)) ; XXX: remove this after we drop 26.x
713+
(eask--pkg-process pkg
714+
(cond
715+
((package-installed-p pkg)
716+
(eask-msg " - %sSkipping %s (%s)... already installed ✗"
717+
eask--action-prefix
718+
name version))
719+
(t
720+
(eask-with-progress
721+
(format " - %sInstalling %s (%s)... " eask--action-prefix name version)
722+
(eask-with-verbosity 'debug
723+
(package-install-file (expand-file-name file)))
724+
"done ✓")))))
725+
672726
(defun eask-package-install (pkg)
673727
"Install the package (PKG)."
674728
(eask-defvc< 27 (eask-pkg-init)) ; XXX: remove this after we drop 26.x
@@ -683,18 +737,17 @@ Argument BODY are forms for execution."
683737
(unless (eask-package-installable-p pkg)
684738
(eask-error "Package not installable `%s'; make sure the package archive (source) is included" pkg))))
685739
(t
686-
(eask--pkg-process pkg
687-
(eask-with-progress
688-
(format " - %sInstalling %s (%s)... " eask--action-prefix name version)
689-
(eask-with-verbosity 'debug
690-
;; XXX: Without ignore-errors guard, it will trigger error
691-
;;
692-
;; Can't find library xxxxxxx.el
693-
;;
694-
;; But we can remove this after Emacs 28, since function `find-library-name'
695-
;; has replaced the function `signal' instead of the `error'.
696-
(eask-ignore-errors (package-install pkg)))
697-
"done ✓"))))))
740+
(eask-with-progress
741+
(format " - %sInstalling %s (%s)... " eask--action-prefix name version)
742+
(eask-with-verbosity 'debug
743+
;; XXX: Without ignore-errors guard, it will trigger error
744+
;;
745+
;; Can't find library xxxxxxx.el
746+
;;
747+
;; But we can remove this after Emacs 28, since function `find-library-name'
748+
;; has replaced the function `signal' instead of the `error'.
749+
(eask-ignore-errors (package-install pkg)))
750+
"done ✓")))))
698751

699752
(defun eask-package-delete (pkg)
700753
"Delete the package (PKG)."
@@ -720,13 +773,12 @@ Argument BODY are forms for execution."
720773
(eask-msg " - %sSkipping %s (%s)... not installed ✗" eask--action-prefix name version))
721774
(t
722775
(eask-pkg-init)
723-
(eask--pkg-process pkg
724-
(eask-with-progress
725-
(format " - %sReinstalling %s (%s)... " eask--action-prefix name version)
726-
(eask-with-verbosity 'debug
727-
(package-delete (eask-package-desc pkg t) t)
728-
(eask-ignore-errors (package-install pkg)))
729-
"done ✓"))))))
776+
(eask-with-progress
777+
(format " - %sReinstalling %s (%s)... " eask--action-prefix name version)
778+
(eask-with-verbosity 'debug
779+
(package-delete (eask-package-desc pkg t) t)
780+
(eask-ignore-errors (package-install pkg)))
781+
"done ✓")))))
730782

731783
(defun eask-package-desc (name &optional current)
732784
"Build package description by its NAME.
@@ -1276,6 +1328,7 @@ This uses function `locate-dominating-file' to look up directory tree."
12761328
(defvar eask-depends-on-emacs nil)
12771329
(defvar eask-depends-on nil)
12781330
(defvar eask-depends-on-dev nil)
1331+
(defvar eask-depends-on nil)
12791332

12801333
(defmacro eask--save-eask-file-state (&rest body)
12811334
"Execute BODY without touching the Eask-file global variables."
@@ -1487,6 +1540,17 @@ argument COMMAND."
14871540

14881541
(add-hook 'eask-file-loaded-hook #'eask--setup-dependencies)
14891542

1543+
(defun eask--check-depends-on (recipe)
1544+
"Return non-nil if RECIPE is invalid."
1545+
(let ((pkg (car recipe))
1546+
(minimum-version (cdr recipe)))
1547+
(cond ((member recipe eask-depends-on)
1548+
(eask-error "Define dependencies with the same name `%s'" pkg))
1549+
((cl-some (lambda (rcp)
1550+
(string= (car rcp) pkg))
1551+
eask-depends-on)
1552+
(eask-error "Define dependencies with the same name `%s' with different version" pkg)))))
1553+
14901554
(defun eask-f-depends-on (pkg &rest args)
14911555
"Specify a dependency (PKG) of this package.
14921556
@@ -1505,17 +1569,27 @@ ELPA)."
15051569
recipe)))
15061570
;; No argument specify
15071571
((<= (length args) 1)
1508-
(let* ((minimum-version (or (car args) "0"))
1572+
(let* ((minimum-version (car args))
15091573
(recipe (list pkg minimum-version)))
1510-
(if (member recipe eask-depends-on)
1511-
(eask-error "Define dependencies with the same name `%s'" pkg)
1574+
(unless (eask--check-depends-on recipe)
1575+
(push recipe eask-depends-on))
1576+
recipe))
1577+
;; Local packages
1578+
((memq :file args)
1579+
(let* ((recipe (append (list (intern pkg)) args)))
1580+
(unless (eask--check-depends-on recipe)
1581+
(push recipe eask-depends-on))
1582+
recipe))
1583+
;; VC packages
1584+
((memq :vc args)
1585+
(let* ((recipe (append (list (intern pkg)) args)))
1586+
(unless (eask--check-depends-on recipe)
15121587
(push recipe eask-depends-on))
15131588
recipe))
15141589
;; recipe are entered
15151590
(t
15161591
(let ((recipe (append (list (intern pkg)) args)))
1517-
(if (member recipe eask-depends-on)
1518-
(eask-error "Define dependencies with the same name `%s'" pkg)
1592+
(unless (eask--check-depends-on recipe)
15191593
(push recipe eask-depends-on)
15201594
(eask-load "extern/github-elpa")
15211595
(eask-with-verbosity 'debug

lisp/core/info.el

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
offset (eask-2str eask-info--max-offset))
2828
(dolist (dep dependencies)
2929
(let* ((target-version (cdr dep))
30-
(target-version (if (= (length target-version) 1)
31-
(nth 0 target-version)
32-
"specified")))
30+
(target-version (cond ((= (length target-version) 1)
31+
(or (nth 0 target-version) ; verison number
32+
"archive"))
33+
((memq :file dep) "file")
34+
((memq :vc dep) "vc")
35+
(t "recipe"))))
3336
(eask-println (concat " %-" offset "s (%s)") (car dep) target-version)
3437
(eask-debug " Recipe: %s" (car dep)))))))
3538

0 commit comments

Comments
 (0)