;;;
;;; NOTE TO SELF: manifest.el. comes before checksum.el
;;;
;;; -------------------------------------------------------------------------------------
;;; (setq manifest--bak-dir "~/bak/")
;;; (setq manifest--bak-file "bakw-h-dlisp")   ;;;ok///\
;;; (setq manifest--bak-file "web-jpg")        ;; ok//|\\
;;;                                            ;; /ok\\|\\
(defun manifest--get-latest-file ()
  (let ((tgz (directory-files manifest--bak-dir
                              nil
                              (concat
                               manifest--bak-file
                               "-[0-9]+-[0-9]+\\.tar\\.gz$")
                              nil))
        (tar (directory-files manifest--bak-dir
                              nil
                              (concat
                               manifest--bak-file
                               "-[0-9]+-[0-9]+\\.tar$")
                              nil)))

    (assert (not (and tgz tar)))
    ;;
    ;; NOTE: order doesn't matter here:
    ;;
    (if tar (car (last tar))
      (car (last tgz))))
  )

(defun manifest--get-file-at-point ()
  "Assumes file has no spaces"
  (save-excursion
    (let (p-end)
      (end-of-line)
      (setq p-end (point))
      (re-search-backward " " nil t)
      (forward-char 1)
      (buffer-substring-no-properties (point) p-end))))

(defun manifest--log-message (msg)
  (save-excursion
    (set-buffer manifest--buffer)
    (goto-char (point-max))
    (setq latest-file (manifest--get-latest-file))
    (insert msg "\n")
    )
  )

;;;
;;; is by looking at the latest tar file
;;;
(defun manifest--compose-latest-tar-file ()
  (let* (;;(manifest--bak-file "foo")
         (latest-file (manifest--get-latest-file))
         (list        nil))
    (save-window-excursion
      (shell-command (concat "tar tvf " manifest--bak-dir latest-file))

      (set-buffer "*Shell Command Output*")
      (goto-char (point-min))

      (if (re-search-forward "Error" nil t)
          (progn
            ;;(debug)
            (error "Cannot find tar file %s%s" manifest--bak-dir latest-file)))

      (while (< (point) (point-max))
        (setq list (cons (manifest--get-file-at-point) list))
        (forward-line 1))
      (setq list (reverse list)))
    )
  )

(defun manifest--write ()
  (setq file (concat manifest--bak-dir manifest--bak-file ".manifest"))
  (if (not (file-exists-p file))
      (shell-command (concat "touch " file)))
  (save-excursion
    (find-file file)
    (erase-buffer)
    (insert (prin1-to-string manifest--list))
    (save-buffer file)
    (kill-buffer nil))
  )

(setq auto-mode-alist (cons '("\\.manifest$" . emacs-lisp-mode) auto-mode-alist))

(defun manifest--read ()

  (let ((file (concat manifest--bak-dir manifest--bak-file ".manifest")))

    (if (not (file-exists-p file))
        (progn
          (manifest--log-message (format "*** File %s does not exist" file))
          (setq manifest--list nil)
          nil)
      (save-excursion
        (find-file file)
        (goto-char (point-min))
        (forward-sexp 1)
        (setq s (buffer-substring-no-properties (point-min) (point)))
        (setq manifest--list (read s))
        (kill-buffer nil)
        t)
      )
    )
  )

(defun manifest--first-write ()
  (condition-case err
      (progn
        (setq manifest--list (manifest--compose-latest-tar-file))
        (manifest--write))
    (error (d-beeps (cadr err)))
    )
  )

(defun manifest--update-add-extra ()
  (let* ((new-list (manifest--compose-latest-tar-file))
         (ptr      new-list)
         (added    nil))
    (while ptr
      (if (not (find (car ptr) manifest--list :test 'string=))
          (progn
            (setq manifest--list (cons (car ptr) manifest--list))
            (setq added t)))
      (setq ptr (cdr ptr)))
    (setq manifest--list (sort manifest--list 'string<))
    added)
  )

(defun manifest--update-error-missing ()
  (let* ((new-list (manifest--compose-latest-tar-file))
         (ptr      manifest--list))
    (while ptr
      (if (not (find (car ptr) new-list :test 'string=))
          (manifest--log-message (concat "*** In " (manifest--get-latest-file) " not found: " (car ptr))))
      (setq ptr (cdr ptr)))
    )
  )

(defun manifest--update ()
  (let ((added nil))
    (when (manifest--read)
      (setq added (manifest--update-add-extra))
      (manifest--update-error-missing)
      (if added (manifest--write))
      )
    )
  )

(setq manifest--bak-dir  "~/bak/")
;;(setq manifest--master-list '("bakw-dlisp" "bakw-h-zallegro"))
;;(setq manifest--master-list '("bakw-h-zallegro"))

(defun manifest--first-write-all ()
  (message "Begin manifest--first-write-all")
  (let ((ptr manifest--master-list))
    (while ptr
      (let ((manifest--bak-file (car ptr)))
        (if (not (file-exists-p (concat manifest--bak-dir manifest--bak-file ".manifest")))
            (manifest--first-write)))
      (setq ptr (cdr ptr))))
  (message "End manifest--first-write-all"))

(defun manifest--update-all ()

  (let ((ptr manifest--master-list)
        (manifest--buffer "*Manifest Errors*"))

    (message "Begin manifest--update-all")

    (save-excursion
      (if (get-buffer manifest--buffer)
          (kill-buffer manifest--buffer))
      (generate-new-buffer manifest--buffer)
      (set-buffer manifest--buffer)
      (erase-buffer))

    ;;(switch-to-buffer manifest--buffer)
    ;;(error "smeg")

    (save-excursion
      (while ptr
        (message "Calling manifest--update on file %s" (car ptr))
        (let ((manifest--bak-file (car ptr)))
          ;;(switch-to-buffer manifest--buffer)
          (manifest--update))
        (setq ptr (cdr ptr))))

    (let (l)
      (switch-to-buffer manifest--buffer)
      (setq l (count-lines (point-min) (point-max)))
      (goto-char (point-max))
      (insert (format "**** %d error%s\n**** Manifest finished\n" l (if (= 1 l) "" "s")))
      (compilation-mode)
      (read-only-mode -1)
      )

    (message "End manifest--update-all")
    )
  )

;;(manifest--first-write-all)

(defun manifest ()
  (interactive)
  (progn
    (setq manifest--master-list '("bakw-h-dlisp"
                                  "bakw-h-rest"
                                  "bakw-h-tallegro"
                                  "bakw-h-yallegro"
                                  "bakw-h-zallegro"
                                  "bakw-info"
                                  "bakw-photos"
                                  "bakw-sound-samples"
                                  "web-jpg"
                                  "web-nojpg"
                                  ))

    (manifest--update-all)
    )
  )

(defun manifest--clean ()
  (mapcar 'delete-file (directory-files manifest--bak-dir t "\\.manifest$"))
  )

(d-quote
 ( 1 2 3 )
 ;;[ )
 )

(provide 'manifest)
;;; manifest.el ends here
