;;; -*- Mode:Zetalisp; Package:USER; Base:10 -*-

;;; code to run in the TI-SYSTEM to restore magtapes.
;;; Just cant trust the winning TI software to do the predictable
;;; right thing for this. Too much hair and not enough functional
;;; arguments.

;;; before using this you must go into the SYSTEM-B thing and do PREPARE-TAPE.


(defun (:no-transform restore-source-directory) (from-dir)
  from-dir)

(defun (:lmi-sys restore-source-directory) (from-dir)
  (append '("LMI-SYS") (if (atom from-dir) (list from-dir) from-dir)))


(defun (:ti-sys restore-source-directory) (from-dir)
  (append '("TI-RELEASE-2") (if (atom from-dir) (list from-dir) from-dir)))

(defun (:gjc-root restore-source-directory) (from-dir)
  (append '("GJC") (if (atom from-dir) (list from-dir) from-dir)))

(defun (:ti-sys-mit restore-source-directory) (from-dir)
  (append '("TI-RELEASE-2") (if (atom from-dir) () (cdr from-dir))))


(defun (:mit-stuff restore-source-directory) (from-dir)
  (append '("MIT-STUFF") (cond ((atom from-dir) (list from-dir))
			       ((null (cdr from-dir)) from-dir)
			       ('else (cdr from-dir)))))


(defun restore-source-tape (to-host &optional (transform-directory :lmi-sys))
  (do ()
      ((not (restore-one-source-file to-host transform-directory)))))


(defun restore-one-source-file (to-host transform-directory)
  (with-open-stream (s (mt:make-mt-file-stream))
    (when (errorp s)
      (format t "~&RESTORE COMPLETE: ~A~%" (send s :report-string))
      (return-from restore-one-source-file nil))
    (let ((byte-size (send s :byte-size))
	  (characters (send s :characters))
	  (author (send s :author))
	  (creation-date (send s :creation-date))
	  (truename (send s :truename)))
      (let ((target-pathname (send truename :new-pathname :host to-host
				   :directory (funcall (get transform-directory 'restore-source-directory)
						       (send truename :directory)))))
	(format t "~&~A => ~A" truename target-pathname)
	(cond ((probe-file-create-dir target-pathname)
	       (format t " already exists"))
	      ('else
	       (restore-one-file-1 s target-pathname (list :byte-size byte-size
							   :characters characters
							   :author author
							   :creation-date creation-date)))))))
  t)

(defun probe-file-create-dir (x)
  (condition-case ()
      (open x :direction nil)
    (fs:directory-not-found
     (let ((name (send x :new-pathname :name nil :type nil :version nil)))
       (format t "~&Creating directory for ~A" name)
       (create-directory-recursive name))
     ())
    (fs:file-lookup-error
     ())))

(defun create-directory-recursive (pathname)
  (condition-case ()
      (fs:create-directory pathname)
    (fs:directory-not-found
     (let ((need (send pathname :new-directory (butlast (send pathname :directory)))))
       (format t "~&Also must create superior ~A" need)
       (create-directory-recursive need))
     (fs:create-directory pathname))))




(DEFVAR *RESTORE-ONE-FILE-PROPERTIES* '(:AUTHOR :CREATION-DATE)
  "Properties to carry over to the new file via a :CHANGE-PROPERTIES message")

(DEFUN RESTORE-ONE-FILE-1 (INSTREAM OUTPUT-PATHNAME PLIST &AUX TIME)
  (SETQ TIME (TIME))
  (WITH-OPEN-FILE (OUTSTREAM OUTPUT-PATHNAME
			     :DIRECTION :OUTPUT
			     :CHARACTERS (GETF PLIST :CHARACTERS)
			     :BYTE-SIZE (GETF PLIST :BYTE-SIZE))
    (LET ((RESTORE-PLIST NIL)
	  (NOT-VALUE (LIST NIL)))
      (DOLIST (P *RESTORE-ONE-FILE-PROPERTIES*)
	(LET ((VALUE (GETF PLIST P NOT-VALUE)))
	  (OR (EQ VALUE NOT-VALUE)
	      (SETF (GETF RESTORE-PLIST P) VALUE))))
      (WHEN RESTORE-PLIST
	(LEXPR-SEND OUTSTREAM :CHANGE-PROPERTIES NIL RESTORE-PLIST)))
    (SETQ TIME (QUOTIENT (TIME-DIFFERENCE (TIME) TIME) 60.0))
    (FORMAT T "~%  ==> ~A (~$ seconds)~%" (SEND OUTSTREAM :TRUENAME) TIME)
    (SETQ TIME (TIME))
    (DO ((BUFFER)
	 (OFFSET)
	 (LIMIT)
	 (BYTES 0))
	(())
      (MULTIPLE-VALUE (BUFFER OFFSET LIMIT)
	(SEND INSTREAM :READ-INPUT-BUFFER))
      (WHEN (NULL BUFFER)
	(SETQ TIME (QUOTIENT (TIME-DIFFERENCE (TIME) TIME) 60.0))
	(FORMAT T
		" copy: ~$ seconds, ~$ bytes per second~%"
		TIME (QUOTIENT BYTES (IF (ZEROP TIME) 1 TIME)))
	(RETURN NIL))
      (INCF BYTES (- LIMIT OFFSET))
      (SEND OUTSTREAM :STRING-OUT BUFFER OFFSET LIMIT)
      (SEND INSTREAM :ADVANCE-INPUT-BUFFER))
    (SETQ TIME (TIME)))
  (SETQ TIME (QUOTIENT (TIME-DIFFERENCE (TIME) TIME) 60.0))
  (FORMAT T " output-close: ~$ seconds" TIME))


