SHA-1-based checking of doc dependencies

This commit is contained in:
Matthew Flatt 2010-04-30 16:12:57 -06:00
parent 259edc0780
commit 17c1dc1ab9
4 changed files with 100 additions and 32 deletions

View File

@ -17,7 +17,9 @@
manager-skip-file-handler
file-stamp-in-collection
file-stamp-in-paths
(rename-out [trace manager-trace-handler]))
(rename-out [trace manager-trace-handler])
get-file-sha1
get-compiled-file-sha1)
(define manager-compile-notify-handler (make-parameter void))
(define trace (make-parameter void))
@ -79,7 +81,7 @@
(or (not date)
(zo-date . > . date)))
(cons zo-date
(delay (get-compiled-sha1 mode (get-zo-path))))]
(delay (get-compiled-file-sha1 (get-zo-path) mode)))]
[date
(cons date
(delay (get-source-sha1 (get-path))))]
@ -574,3 +576,11 @@
"empty use-compiled-file-paths list: "
modes))
compilation-manager-load-handler))
;; Exported:
(define (get-compiled-file-sha1 path)
(try-file-sha1 path (path-replace-suffix path #".dep")))
(define (get-file-sha1 path)
(get-source-sha1 path))

View File

@ -82,12 +82,13 @@ would create only @filepath{compiled/b_scm.zo} and
In addition to a bytecode file, @|mzc| creates a file
@filepath{compiled/@nonterm{name}_@nonterm{ext}.dep} that records
dependencies of the compiled module on other module files. Using this
dependency information, a re-compilation request via @|mzc| can
consult both the source file's timestamp and the timestamps for the
sources and bytecode of imported modules. Furthermore, imported
modules are themselves compiled as necessary, including updating the
bytecode and dependency files for the imported modules, transitively.
dependencies of the compiled module on other module files and the
source file's SHA-1 hash. Using this dependency information, a
re-compilation request via @|mzc| can consult both the source file's
timestamp/hash and the timestamps/hashes for the bytecode of imported
modules. Furthermore, imported modules are themselves compiled as
necessary, including updating the bytecode and dependency files for
the imported modules, transitively.
Continuing the @exec{mzc a.scm} example from the previous section, the
@|mzc| creates @filepath{compiled/a_scm.dep},
@ -96,7 +97,7 @@ the same time as the @filepath{.zo} files. The
@filepath{compiled/a_scm.dep} file records the dependency of
@filepath{a.scm} on @filepath{b.scm}, @filepath{c.scm} and the
@schememodname[scheme] library. If the @filepath{b.scm} file is
modified (so that its timestamp changes), then running
modified (so that its timestamp and SHA-1 hash changes), then running
@commandline{mzc a.scm}
@ -153,7 +154,9 @@ file if
first sub-directory listed in @scheme[use-compiled-file-paths]
(at the time that
@scheme[make-compilation-manager-load/use-compiled-handler]
was called)}
was called), and either no @filepath{.dep} file exists or it
records a source-file SHA-1 hash that differs from the current
version and source-file SHA-1 hash;}
@item{no @filepath{.dep} file exists next to the @filepath{.zo}
file;}
@ -162,19 +165,28 @@ file if
match the result of @scheme[(version)];}
@item{one of the files listed in the @filepath{.dep} file has a
@filepath{.zo} timestamp newer than the one recorded in the
@filepath{.dep} file.}
@filepath{.zo} timestamp newer than the target @filepath{.zo},
and the combined hashes of the dependencies recorded in the
@filepath{.dep} file does not match the combined hash recorded
in the @filepath{.dep} file.}
]}
]
If SHA-1 hashes override a timestamp-based decision to recompile the
file, then the target @filepath{.zo} file's timestamp is updated to
the current time.
After the handler procedure compiles a @filepath{.zo} file, it creates
a corresponding @filepath{.dep} file that lists the current version,
plus the @filepath{.zo} timestamp for every file that is
a corresponding @filepath{.dep} file that lists the current version
and the identification of every file that is directly
@scheme[require]d by the module in the compiled file. Additional
dependencies can be installed during compilation via
@schememodname[compiler/cm-accomplice].
@schememodname[compiler/cm-accomplice]. The @filepath{.dep} file also
records the SHA-1 hash of the module's source, and it records a
combined SHA-1 hash of all of the dependencies that includes their
recursive dependencies.
The handler caches timestamps when it checks @filepath{.dep} files,
and the cache is maintained across calls to the same handler. The
@ -266,6 +278,21 @@ Returns the file-modification date and @scheme[delay]ed hash of
This function is intended for use with @scheme[manager-skip-file-handler].}
@defproc[(get-file-sha1 [p path?]) (or/c string? #f)]{
Computes a SHA-1 hash for the file @racket[p]; the result is
@racket[#f] if @racket[p] cannot be opened.}
@defproc[(get-compiled-file-sha1 [p path?]) (or/c string? #f)]{
Computes a SHA-1 hash for the bytecode file @racket[p], appending any
dependency-describing hash available from a @filepath{.dep} file when
available (i.e., the suffix on @racket[p] is replaced by
@filepath{.dep} to locate dependency information). The result is
@racket[#f] if @racket[p] cannot be opened.}
@; ----------------------------------------------------------------------
@section{Compilation Manager Hook for Syntax Transformers}

View File

@ -2,7 +2,7 @@
@(require scribble/bnf
"utils.ss")
@title{@bold{Scribble}: PLT Documentation Tool}
@title{@bold{Scribble}: Racket Documentation Tool}
@author["Matthew Flatt" "Eli Barzilay"]

View File

@ -10,6 +10,7 @@
scheme/file
scheme/fasl
scheme/serialize
compiler/cm
syntax/modread
scribble/base-render
scribble/core
@ -379,37 +380,60 @@
(define (make-sci-computed sci)
(lambda () sci))
(define (file-or-directory-modify-seconds/stamp file
stamp-time stamp-data pos
get-sha1)
(let ([t (file-or-directory-modify-seconds file #f (lambda () +inf.0))])
(cond
[(t . <= . stamp-time) stamp-time]
[(equal? (list-ref stamp-data pos) (get-sha1 file)) stamp-time]
[else t])))
(define ((get-doc-info only-dirs latex-dest auto-main? auto-user?
with-record-error setup-printf)
doc)
(let* ([info-out-file (build-path (or latex-dest (doc-dest-dir doc)) "out.sxref")]
[info-in-file (build-path (or latex-dest (doc-dest-dir doc)) "in.sxref")]
[stamp-file (build-path (or latex-dest (doc-dest-dir doc)) "stamp.sxref")]
[out-file (build-path (doc-dest-dir doc) "index.html")]
[src-zo (let-values ([(base name dir?) (split-path (doc-src-file doc))])
(build-path base "compiled" (path-add-suffix name ".zo")))]
[renderer (make-renderer latex-dest doc)]
[can-run? (can-build? only-dirs doc)]
[aux-time (max (file-or-directory-modify-seconds
(build-path (collection-path "scribble")
"compiled"
(path-add-suffix
(if latex-dest
"latex-render.ss"
"html-render.ss")
".zo"))
#f (lambda () -inf.0))
(file-or-directory-modify-seconds
(build-path (collection-path "scribble")
"scribble.css")
#f (lambda () +inf.0)))]
[stamp-time (file-or-directory-modify-seconds stamp-file #f (lambda () -inf.0))]
[stamp-data (with-handlers ([exn:fail:filesystem? (lambda (exn) (list "" "" ""))])
(let ([v (call-with-input-file* stamp-file read)])
(if (and (list? v)
(= 3 (length v))
(andmap string? v))
v
(list "" "" ""))))]
[renderer-path (build-path (collection-path "scribble")
"compiled"
(path-add-suffix
(if latex-dest
"latex-render.rkt"
"html-render.rkt")
".zo"))]
[css-path (build-path (collection-path "scribble")
"scribble.css")]
[aux-time (max (file-or-directory-modify-seconds/stamp
renderer-path
stamp-time stamp-data 1
get-compiled-file-sha1)
(file-or-directory-modify-seconds/stamp
css-path
stamp-time stamp-data 2
get-file-sha1))]
[my-time (file-or-directory-modify-seconds out-file #f (lambda () -inf.0))]
[info-out-time (file-or-directory-modify-seconds info-out-file #f (lambda () #f))]
[info-in-time (file-or-directory-modify-seconds info-in-file #f (lambda () #f))]
[info-time (min (or info-out-time -inf.0) (or info-in-time -inf.0))]
[vers (send renderer get-serialize-version)]
[src-time (max aux-time
(file-or-directory-modify-seconds
src-zo #f (lambda () +inf.0)))]
[src-time (file-or-directory-modify-seconds/stamp
src-zo
stamp-time stamp-data 0
get-compiled-file-sha1)]
[up-to-date?
(and info-out-time
info-in-time
@ -535,6 +559,13 @@
(unless latex-dest
(render-time "xref-in" (write-in info)))
(set-info-need-in-write?! info #f))
(when (or (stamp-time . < . aux-time)
(stamp-time . < . src-time))
(let ([data (list (get-compiled-file-sha1 src-zo)
(get-compiled-file-sha1 renderer-path)
(get-file-sha1 css-path))])
(with-output-to-file stamp-file #:exists 'truncate/replace (lambda () (write data)))
(file-or-directory-modify-seconds stamp-file (max aux-time src-time))))
info))))
(lambda () #f))
#f))))