md5 works now. (rule ...) is now called (file ...).

This commit is contained in:
jottbee 2005-02-14 07:41:34 +00:00
parent 7115ec2769
commit b7ba049edd
1 changed files with 122 additions and 175 deletions

View File

@ -1,209 +1,156 @@
;;; TODO:
;;;
;;; (update-md-sum ...) is (due to history) not very lucky
;;;
(define digest-files (list "checksums.md5"
"fingerprints.md5"
"digests.md5"))
(define digest-extensions (list ".md5" ".fp" ".digest")) (define digest-extensions (list ".md5" ".fp" ".digest"))
(define (make-rule-build-func target prereqs thunk) (define (make-file-build-func target prereqs thunk)
(lambda args (lambda args
; (breakpoint "make-file-build-func")
(let ((cooked-state (last args))
(prereqs-results (cdr (reverse (cdr args)))))
(cons (begin (cons (begin
(display ";;; rule : ") (display ";;; rule : ")
(display target) (display target)
(newline) (newline)
(thunk)) (bind-fluids-gnu target prereqs prereqs-results thunk))
(last args)))) cooked-state))))
(define (make-md5-build-func target prereqs thunk) (define (make-md5-build-func target prereqs thunk)
(lambda args (lambda args
; (breakpoint "make-md5-build-func")
(let ((cooked-state (last args))
(prereqs-results (cdr (reverse (cdr args)))))
(cons (begin (cons (begin
(display ";;; md5 : ") (display ";;; md5 : ")
(display target) (display target)
(newline) (newline)
(thunk)) (bind-fluids-gnu target prereqs prereqs-results thunk))
(last args)))) cooked-state))))
(define (make-always-build-func target prereqs thunk) (define (make-always-build-func target prereqs thunk)
(lambda args (lambda args
; (breakpoint "make-always-build-func")
(let ((cooked-state (last args))
(prereqs-results (cdr (reverse (cdr args)))))
(cons (begin (cons (begin
(display ";;; always : ") (display ";;; always : ")
(display target) (display target)
(newline) (newline)
(thunk)) (bind-fluids-gnu target prereqs prereqs-results thunk))
(last args)))) cooked-state))))
(define (make-once-build-func target prereqs thunk) (define (make-once-build-func target prereqs thunk)
(lambda args (lambda args
; (breakpoint "make-once-build-func")
(let ((cooked-state (last args))
(prereqs-results (cdr (reverse (cdr args)))))
(cons (begin (cons (begin
(display ";;; once : ") (display ";;; once : ")
(display target) (display target)
(newline) (newline)
(thunk)) (bind-fluids-gnu target prereqs prereqs-results thunk))
(last args)))) cooked-state))))
(define (make-is-out-of-date! target . prereqs) (define (make-is-out-of-date! target . prereqs)
;; init-state is the last arg (lambda args
;; pass it untouched to the result ; (breakpoint "make-is-out-of-date!")
(lambda args (cons #t (last args)))) (let ((init-state (last args)))
(cons #t init-state))))
(define (make-once target . prereqs) (define (make-once target . prereqs)
;; init-state is the last arg (lambda args
;; pass it untouched to the result ; (breakpoint "make-once")
(lambda args (cons (file-not-exists? target) (last args)))) (let ((init-state (last args)))
(cons (file-not-exists? target) init-state))))
(define (make-is-out-of-date? target . prereqs) (define (make-is-out-of-date? target . prereqs)
(lambda args (lambda args
; (breakpoint "make-is-out-of-date?")
(let ((init-state (last args))) (let ((init-state (last args)))
(cons (or (file-not-exists? target) (cons (or (file-not-exists? target)
(and (not (null? prereqs)) (and (not (null? prereqs))
(let for-each-prereq ((prereq (car prereqs)) (let for-each-prereq ((prereq (car prereqs))
(todo (cdr prereqs))) (todo (cdr prereqs)))
(and (file-exists? prereq) (cond
(> (file-last-mod prereq) ((file-not-exists? prereq) #t)
(file-last-mod target)) ((> (file-last-mod prereq) (file-last-mod target)) #t)
(or (null? todo) ((null? todo) #f)
(for-each-prereq (car todo) (cdr todo))))))) (else (for-each-prereq (car todo) (cdr todo)))))))
init-state)))) init-state))))
(define (make-md5-sum-changed? target . prereqs) (define (make-md5-sum-changed? target . prereqs)
(lambda args (lambda args
(let ((init-state (last args)) ; (breakpoint "make-md5-sum-changed?")
(tfname (expand-file-name target (cwd)))) (let ((init-state (last args)))
(cons (or (file-not-exists? tfname) (cons (not (same-checksum? target digest-extensions prereqs))
(or (null? prereqs)
(let for-each-prereq ((prereq (car prereqs))
(todo (cdr prereqs)))
(let ((pname (expand-file-name prereq (cwd))))
(or (and (file-exists? pname)
(> (file-last-mod pname)
(file-last-mod tfname))
(checksum-changed? pname)
(or (md5-sum-update pname) #t))
(and (not (null? todo))
(for-each-prereq (car todo) (cdr todo))))))))
init-state)))) init-state))))
(define (check-files-target+extensions target checksum) (define (checksum-from-file basename extension)
(map (lambda (digest-file) (let* ((bname (string-append basename extension))
(lambda () (file (expand-file-name bname (cwd))))
(let ((dfile (expand-file-name digest-file (cwd)))) (if (file-exists? file)
(or (file-not-exists? dfile) (let* ((outport (open-input-file file))
(let ((strls (port->string-list (open-input-file dfile)))) (strls (port->string-list outport)))
(= checksum ;; (display ";;; using : ") (display bname) (newline)
(string->number (if (null? strls) "" (car strls))))))))) (if (null? strls)
(map (lambda (ext)
(string-append target ext))
digest-extensions)))
(define (update-files-target+extensions target checksum)
(map (lambda (digest-file)
(lambda ()
(let ((dfile (expand-file-name digest-file (cwd))))
(and (file-exists? dfile)
(let ((outport (open-output-file dfile)))
(display ";;; update : ") (display target) (newline)
(with-current-output-port
outport
(lambda ()
(display (number->string checksum)) (newline)))
(close outport)
#t)))))
(map (lambda (ext)
(string-append target ext))
digest-extensions)))
(define (digest-file->string-list digest-fname)
(let* ((inport (open-input-file (expand-file-name digest-fname (cwd))))
(strls (map (lambda (str)
(let ((ls (string-tokenize str)))
(if (not (null? ls))
(let ((fp (car ls))
(name (cadr ls)))
(cons name fp))
'())))
(port->string-list inport))))
(close inport)
strls))
(define (check-digest-files target checksum)
(map (lambda (digest-file)
(lambda ()
(let ((dfile (expand-file-name digest-file (cwd)))
(tname (file-name-nondirectory target)))
(or (file-not-exists? dfile)
(let* ((*fname-md5* (digest-file->string-list dfile))
(maybe-md5 (if (or (null? *fname-md5*)
(null? (car *fname-md5*)))
#f #f
(assoc tname *fname-md5*)))) (string->number (car strls))))
(or (not maybe-md5) #f)))
(= checksum
(string->number (cdr maybe-md5)))))))))
digest-files))
(define (string-list->digest-file dfname strls) (define (checksum-into-file basename extension checksum)
(let ((outport (open-output-file (expand-file-name dfname (cwd)))) (let* ((bname (string-append basename extension))
(names (if (or (null? strls) (null? (car strls))) '() (map car strls))) (file (expand-file-name bname (cwd)))
(sums (if (or (null? strls) (null? (car strls))) '() (map cdr strls)))) (outport (open-output-file file))
(display ";;; update : ") (display dfname) (newline) (str (number->string checksum)))
(for-each (lambda (name fp) ;; (display ";;; update : ") (display bname) (newline)
(with-current-output-port outport (with-current-output-port outport (begin (display str) (newline)))
(for-each display (list fp " " name)) (close outport)))
(newline)))
names sums)
(close outport)
#t))
(define (update-digest-files target checksum) (define (checksum-for-file fname)
(map (lambda (digest-file) (let ((file (expand-file-name fname (cwd))))
(lambda () (and (file-exists? file)
(let ((dfile (expand-file-name digest-file (cwd))) (md5-digest->number (md5-digest-for-port (open-input-file file))))))
(tname (file-name-nondirectory target)))
(and (file-exists? dfile)
(let* ((*fname-md5* (digest-file->string-list dfile))
(cleaned-table (if (or (null? *fname-md5*)
(null? (car *fname-md5*)))
(list)
(alist-delete tname *fname-md5*))))
(string-list->digest-file
dfile
(alist-cons tname checksum cleaned-table)))))))
digest-files))
(define (checksum-changed? target) ;;; optimizations possible: global variable with known checksums
(let* ((inport (open-input-file target)) (define (get-file-checksum fname)
(checksum (md5-digest->number (md5-digest-for-port inport))) (checksum-for-file fname))
(result-funcs (append (check-files-target+extensions target checksum)
(check-digest-files target checksum))))
(close inport)
(not (let each-result-and ((current (car result-funcs))
(todo (cdr result-funcs)))
(let ((res (current)))
(and res
(or (null? todo)
(each-result-and (car todo) (cdr todo)))))))))
(define (md5-sum-update target) (define (same-checksum? target extensions prereqs)
(let* ((tname (expand-file-name target (cwd))) (or (null? prereqs)
(inport (open-input-file tname)) (let for-each-prereq ((current-prereq (car prereqs))
(checksum (md5-digest->number (md5-digest-for-port inport))) (previous-total 0)
(update-funcs (append (update-files-target+extensions target checksum) (todo-prereqs (cdr prereqs)))
(update-digest-files target checksum)))) (let* ((current-file-sum (get-file-checksum current-prereq))
(close inport) (current-total (if current-file-sum
(let ((update-ok? (lambda () (+ current-file-sum previous-total)
(let each-update-and ((current (car update-funcs)) previous-total)))
(todo (cdr update-funcs))) (cond
(or (current) ((and (not (null? todo-prereqs)))
(and (not (null? todo)) (for-each-prereq (car todo-prereqs)
(each-update-and (car todo) (cdr todo)))))))) current-total
;; the default is to use the filename with .md5 extension (cdr todo-prereqs)))
(if (not (update-ok?)) ((and (null? todo-prereqs) (not (null? extensions)))
(let ((outport (open-output-file (string-append tname ".md5")))) (let for-each-ext ((ext (car extensions))
(with-current-output-port outport (todo-exts (cdr extensions)))
(let ((known-sum (checksum-from-file target ext)))
(cond
((and (file-not-exists? target) known-sum)
(begin (begin
(display checksum) (checksum-into-file target ext current-total)
(newline))) #f))
(close outport)))))) ((and (file-not-exists? target) (null? todo-exts))
(begin
(checksum-into-file target
(last (reverse extensions))
current-total)
#f))
((and known-sum (= current-total known-sum)) #t)
((and known-sum (not (= current-total known-sum)))
(begin
(checksum-into-file target ext current-total)
#f))
((and (not known-sum) (not (null? todo-exts)))
(for-each-ext (car todo-exts) (cdr todo-exts)))
((and (not known-sum) (null? todo-exts))
(begin
(checksum-into-file target ext current-total)
#f))
(else (error "no match in same-checksum?"))))))
(else (error "no match in same-checksum?")))))))