;;; core/install-file.el --- Install packages from files, .tar files, or directories  -*- lexical-binding: t; -*-

;;; Commentary:
;;
;; Command use to install packages from files, .tar files, or directories
;;
;;   $ eask install-file [files..]
;;
;;
;;  Positionals:
;;
;;    [files..]     files to install as packages; it will install through the
;;                  function `package-install-file'
;;

;;; Code:

(let ((dir (file-name-directory (nth 1 (member "-scriptload" command-line-args)))))
  (load (expand-file-name "_prepare.el"
                          (locate-dominating-file dir "_prepare.el"))
        nil t))

(eask-load "core/install")

(defun eask-install-file--get-package-name (path)
  "Get the package name from PATH, which is a file, directory or archive."
  (cond
   ((not (file-exists-p path))
    (eask-error "File does not exist %s" path))
   ;; TAR file
   ((string-match-p "[.]+tar[.]*" path)
    ;; Note this can throw strange errors if
    ;;
    ;; - there is no -pkg.el in the tar file
    ;; - the tar file was built in a folder with a different name
    ;;
    ;; TAR files created with eask package are fine.
    (require 'tar-mode)
    (let ((pkg-desc (with-current-buffer (find-file (expand-file-name path))
                      (eask-ignore-errors-silent (package-tar-file-info)))))
      (unless pkg-desc
        ;; `package-dir-info' will return nil if there is no `-pkg.el'
        ;; and no `.el' files at path
        (eask-error "No package in %s" path))
      (package-desc-name pkg-desc)))
   ;; .el file or directory
   (t
    ;; Note `package-dir-info' doesn't work outside of dired mode!
    (let ((pkg-desc (with-current-buffer (dired (expand-file-name path))
                      (eask-ignore-errors-silent (package-dir-info)))))
      (unless pkg-desc
        ;; `package-dir-info' will return nil if there is no `-pkg.el'
        ;; and no `.el' files at path
        (eask-error "No package in %s" path))
      (package-desc-name pkg-desc)))))

(defun eask-install-file--packages (files)
  "The file install packages with FILES."
  (let* ((deps (mapcar (lambda (file)
                         (list (eask-install-file--get-package-name file) file))
                       files))
         (names (mapcar #'car deps))
         (len (length deps))
         (s (eask--sinr len "" "s"))
         (not-installed (eask-install--not-installed names))
         (installed (length not-installed))
         (skipped (- len installed)))
    (eask-log "Installing %s specified file package%s..." len s)
    (eask-msg "")
    (eask--package-mapc (lambda (dep &rest _)
                          (apply #'eask-package-install-file dep))
                        deps)
    (eask-msg "")
    (eask-info "(Total of %s file package%s installed, %s skipped)"
               installed s skipped)))

(eask-start
  (eask-pkg-init)
  (if-let* ((files (eask-args)))
      ;; If package [files..] are specified, we try to install it
      (eask-install-file--packages files)
    ;; Otherwise, report error.
    (eask-info "(No file packages have been installed)")
    (eask-help "core/install-file")))

;;; core/install-file.el ends here
