#lang scribble/doc @(require scribble/manual (for-label "../fs.ss")) @title[#:tag "fs" #:style '(toc)]{Subversion File System} @local-table-of-contents[] @defmodule[(planet "fs.ss" ("murphy" "svn.plt" 1 0))]{ This module provides access to (sub)versioned file systems. Direct Subversion file system access operates on a lower level than repository access – for example creating a file system does not create some of the management files of a repository and the direct file system access functions don't care about things like repository hooks. } @section{Filesystems} @deftogether[( @defthing[_fs ctype?] @defthing[_fs/null ctype?] )]{ C pointer type representing file system objects. } @defproc[(fs? [obj any/c]) any]{ Checks whether the given @scheme[obj] is a file system object. } @defproc[(fs-create [path path-string?]) fs?]{ Creates a new Subversion file system at @scheme[path]. } @defproc[(fs-open [path path-string?]) fs?]{ Opens an existing Subversion file system at @scheme[path]. } @defproc[(fs-hotcopy [source path-string?] [target path-string?] [clean? any/c]) void?]{ Creates a new Subversion file system at @scheme[target] that is a duplicate of the existing one at @scheme[source]. The @scheme[clean?] argument determines whether the source filesystem is cleaned up during the process. } @defproc[(fs-delete-fs [path path-string?]) void?]{ Deletes the Subversion file system at @scheme[path]. } @defproc[(fs-type [path path-string?]) symbol?]{ Determines the type of the Subversion file system at @scheme[path]. Returns a symbol naming the file system type, for example @scheme['bdb] or @scheme['fsfs]. } @defproc[(fs-path [fs fs?]) path?]{ Retrieves the location of the file system @scheme[fs] on the disk. } @deftogether[( @defproc[(fs-uuid [fs fs?]) bytes?] @defproc[(set-fs-uuid! [fs fs?] [uuid (or/c bytes? #f)]) void?] @defform[#:id set!/fs-uuid #:literals (set! fs-uuid) (set! (fs-uuid fs) uuid)] )]{ Retrieves or sets the universal ID of the file system as a binary string. When the universal ID is set to @scheme[#f], a new ID is computed for the file system. } @section{Access Contexts} @deftogether[( @defthing[_fs-access ctype?] @defthing[_fs-access/null ctype?] )]{ C pointer type representing file system access contexts. } @defproc[(fs-access? [obj any/c]) any]{ Checks whether the given @scheme[obj] is a file system access context. } @defproc[(make-fs-access [username string?]) fs-access?]{ Creates a new file system access context for the user called @scheme[username]. } @defproc[(fs-access-username [context fs-access?]) string?]{ Retrieves the name of the user represented by the given access @scheme[context]. } @defproc[(fs-access-add-lock-token! [context fs-access?] [token bytes?]) void?]{ Adds the lock identified by @scheme[token] to the given access @scheme[context]. This is necessary when committing to locked nodes. } @deftogether[( @defproc[(fs-access [fs fs?]) (or/c fs-access? #f)] @defproc[(set-fs-access! [fs fs?] [context (or/c fs-access? #f)]) void?] @defform[#:id set!/fs-access #:literals (set! fs-access) (set! (fs-access fs) context)] )]{ Retrieves or sets the access context of a file system. An access context value of @scheme[#f] means that no context is associated with the file system. Setting the context to @scheme[#f] disassociates any present context from the file system. } @section{Revisions} @defproc[(fs-youngest-rev [fs fs?]) exact-nonnegative-integer?]{ Retrieves the number of the youngest revision that has been committed to the file system. } @deftogether[( @defproc[(fs-rev-prop [fs fs?] [rev exact-nonnegative-integer?] [prop-name symbol?]) (or/c bytes? #f)] @defproc[(set-fs-rev-prop [fs fs?] [rev exact-nonnegative-integer?] [prop-name symbol?] [value (or/c bytes? #f)]) void?] @defform[#:id set!/fs-rev-prop #:literals (set! fs-rev-prop) (set! (fs-rev-prop fs rev prop-name) value)] )]{ Retrieves or sets a revision property as a binary string. A non-existent property is represented by the value @scheme[#f]. When a property is set to @scheme[#f], it is deleted. } @defproc[(fs-list-rev-props [fs fs?] [rev exact-nonnegative-integer?]) (listof symbol?)]{ Retrieves a list of all properties set on a revision. } @defproc[(fs-deltify-rev [fs fs?] [rev exact-nonnegative-integer?]) void?]{ Tries to conserve space in the file system by storing changes leading up to the given revision as deltas. } @section{Locks} @defstruct[lock-info ([path path?] [token bytes?] [owner string?] [comment (or/c string? #f)] [creation-time time?] [expiration-time (or/c time? #f)])]{ A structure containing information about a lock. The @scheme[path] and @scheme[token] can be used to identify the lock in @scheme[fs-access-add-lock-token!], @scheme[fs-lock!] and @scheme[fs-unlock!] operations. } @defproc[(fs-lock! [fs fs?] [path path-string?] [#:token token (or/c bytes? #f) #f] [#:comment comment (or/c string? #f) #f] [#:expiration-time expiration-time (or/c time? #f) #f] [#:current-rev current-rev (or/c exact-nonnegative-integer? #f) #f] [#:steal steal? any/c #f]) lock-info?]{ Locks the specified @scheme[path] in the file system @scheme[fs]. The file system must have an associated access context, the user of the access context becomes the owner of the lock. The @scheme[token] uniquely identifies the lock. If it is not specified, a fresh token is generated for the lock. If it is specified and a lock with that token already exists, it must be installed at the same path as the new lock. The @scheme[comment] is purely descriptive and need not be specified. An @scheme[expiration-time] is optional. If specified, it must be a SRFI-19 UTC time or a duration. A duration is added to the current time to produce a value to be passed to the Subversion library. Locks without expiration time never expire. If a @scheme[current-rev] is specified, the lock operation only succeeds if the path hasn't been modified or deleted since that revision. If @scheme[steal?] is not @scheme[#f], any existing lock at the given path is removed and replaced by a new one. } @defproc[(fs-unlock! [fs fs?] [path path-string?] [token (or/c bytes? #f)]) void?]{ Unlocks the specified @scheme[path] in the file system @scheme[fs]. Fails if the lock is expired or no lock is present at all. If @scheme[token] is @scheme[#f], the lock at the given path is broken regardless of its owner. } @defproc[(call-with-fs-lock [fs fs?] [path path-string?] [thunk (-> any)] [#:token token (or/c bytes? #f) #f] [#:comment comment (or/c string? #f) #f] [#:expiration-time expiration-time (or/c time? #f) #f] [#:current-rev current-rev (or/c exact-nonnegative-integer? #f) #f] [#:steal steal? any/c #f]) any]{ Calls the given @scheme[thunk] in a dynamic context, that establishes a lock at @scheme[path] in the file system @scheme[fs] upon entry and releases the lock upon exit. When the lock is established, its token is also added to the current access context of the file system. See @scheme[fs-lock!] for the precise meaning of the keyword arguments. } @defproc[(fs-lock-info [fs fs?] [path path-string?]) (or/c lock-info? #f)]{ Checks for the presence of a lock at @scheme[path] in the file system @scheme[fs]. Returns a lock information object, if there is a lock and @scheme[#f] otherwise. } @defproc[(fs-list-locks [fs fs?] [path path-string?]) (listof lock-info?)]{ Retrieves a list of lock information objects for any locks at or below @scheme[path] in file system @scheme[fs]. } @section{Transactions} @deftogether[( @defthing[_fs-txn ctype?] @defthing[_fs-txn/null ctype?] )]{ C pointer type representing transaction objects. } @defproc[(fs-txn? [obj any/c]) any]{ Checks whether the given @scheme[obj] is a transaction object. } @defproc[(fs-begin-txn [fs fs?] [rev exact-nonnegative-integer?]) fs-txn?]{ Creates a new transaction in @scheme[fs], based on revision @scheme[rev]. } @defproc[(fs-open-txn [fs fs?] [txn-name bytes?]) fs-txn?]{ Opens an existing transaction in @scheme[fs] with the given binary @scheme[txn-name]. } @defproc[(fs-commit-txn [txn fs-txn?]) exact-nonnegative-integer?]{ Commits the transaction @scheme[txn]. Returns the new revision number representing the committed data. } @defproc[(fs-abort-txn [txn fs-txn?]) void?]{ Aborts the transaction @scheme[txn]. } @defproc[(fs-purge-txn [fs fs?] [txn-name bytes?]) void?]{ Purges the inactive transaction with the binary name @scheme[txn-name] from @scheme[fs]. } @defproc[(fs-txn-name [txn fs-txn?]) bytes?]{ Retrieves the binary name of the given transaction. } @defproc[(fs-txn-base-rev [txn fs-txn?]) exact-nonnegative-integer?]{ Retrieves the base revision number of the given transaction. } @deftogether[( @defproc[(fs-txn-prop [txn fs-txn?] [prop-name symbol?]) (or/c bytes? #f)] @defproc[(set-fs-txn-prop! [txn fs-txn?] [prop-name symbol?] [value (or/c bytes? #f)]) void?] @defform[#:id set!/fs-txn-prop #:literals (set! fs-txn-prop) (set! (fs-txn-prop txn prop-name) value)] )]{ Retrieves or sets a transaction property as a binary string. A non-existent property is represented by the value @scheme[#f]. When a property is set to @scheme[#f], it is deleted. } @defproc[(fs-list-txn-props [txn fs-txn?]) (listof symbol?)]{ Retrieves a list of all properties set on a transaction. } @defproc[(fs-list-txns [fs fs?]) (listof fs-txn?)]{ Lists the binary names of all active transactions in the file system @scheme[fs]. } @defproc[(call-with-fs-txn [fs fs?] [rev exact-nonnegative-integer?] [proc (-> txn? any)]) any]{ Creates a new transaction in the file system @scheme[fs] with base revision @scheme[rev]. Applies @scheme[proc] to the new transaction and commits the transaction. If the dynamic context of the @scheme[call-with-fs-txn] expression is left after the transaction has been started but before it has been committed, the transaction is aborted. Returns the new revision number containing the data committed in the transaction and all values (except the first one if it satisfies @scheme[void?]) returned by @scheme[proc]. } @section{Filesystem Roots} @deftogether[( @defthing[_fs-root ctype?] @defthing[_fs-root/null ctype?] )]{ C pointer type representing file system root objects. } @defproc[(fs-root? [obj any/c]) any]{ Checks whether the given @scheme[obj] is a file system root object. } @defproc[(fs-rev-root [fs fs?] [rev exact-nonnegative-integer?]) fs-root?]{ Retrieves the root of revision @scheme[rev] in @scheme[fs]. Data can be read from files via a revision root, but they are immutable. } @defproc[(fs-txn-root [txn fs-txn?]) fs-root?]{ Retrieves the root of the transaction @scheme[txn]. Data can be read from and written to files via a transaction root. When the transaction is committed, data written to files becomes visible outside the transaction in a new revision. } @defproc[(fs-txn-root? [root fs-root?]) boolean?]{ Checks whether the given file system root is a transaction root. } @defproc[(fs-txn-root-name [root fs-root?]) (or/c bytes? #f)]{ Retrieves the binary name of the transaction to which the given @scheme[root] belongs. If the root is not a transaction root, the procedure returns @scheme[#f]. } @defproc[(fs-root-fs [root fs-root?]) fs?]{ Retrieves the file system to which the given @scheme[root] belongs. } @section{Nodes} @defproc[(fs-make-directory [root fs-root?] [path path-string?]) void?]{ Creates a new directory at @scheme[path] below @scheme[root]. } @defproc[(fs-make-file [root fs-root?] [path path-string?]) void?]{ Creates a new empty file at @scheme[path] below @scheme[root]. } @defproc[(fs-copy-node [src-root fs-root?] [src-path path-string?] [tgt-root fs-root?] [tgt-path path-string?]) void?]{ Copies the file at @scheme[src-path] below @scheme[src-root] to @scheme[tgt-path] below @scheme[tgt-root]. Records copy history for the new file. } @defproc[(fs-rev-link-node [src-root fs-root?] [tgt-root fs-root?] [path path-string?]) void?]{ Links the file at @scheme[path] below @scheme[src-root] to the same path below @scheme[tgt-root]. Does not record copy history for the file. } @defproc[(fs-merge-nodes [src-root fs-root?] [src-path path-string?] [tgt-root fs-root?] [tgt-path path-string?] [ancestor-root fs-root?] [ancestor-path path-string?]) void?]{ Merges changes from the ancestor at @scheme[ancestor-path] below @scheme[ancestor-root] the source at @scheme[src-path] below @scheme[scr-root] and between the ancestor and the target at @scheme[tgt-path] below @scheme[tgt-root] into the target. } @defproc[(fs-delete-node [root fs-root?] [path path-string?]) void?]{ Deletes the node at @scheme[path] below @scheme[root]. } @defthing[_fs-node-kind ctype?]{ C enumeration type classifying the node at a given path. The possible values are @scheme['none], @scheme['file], @scheme['dir] and @scheme['unknown]. } @defproc[(fs-node-kind [root fs-root?] [path path-string?]) (one-of/c 'none 'file 'dir 'unknown)]{ Classifies the node at @scheme[path] below @scheme[root]. Returns a symbol describing the type of node or @scheme['none] to indicate that no node exists at the given path. } @deftogether[( @defproc[(fs-node-directory? [root fs-root?] [path path-string?]) boolean?] @defproc[(fs-node-file? [root fs-root?] [path path-string?]) boolean?] )]{ Checks whether a node at @scheme[path] below @scheme[root] exists and is a directory or file respectively. } @defproc[(fs-node-created-rev [root fs-root?] [path path-string?]) (or/c exact-nonnegative-integer? #f)]{ Retrieves the revision in which the node at @scheme[path] below @scheme[root] was created. Returns @scheme[#f] for nodes that have not been committed, yet. } @defproc[(fs-node-created-path [root fs-root?] [path path-string?]) path?]{ Retrieves the path at which the node at @scheme[path] below @scheme[root] was originally created. } @defproc[(fs-node-copied-from [root fs-root?] [path path-string?]) (values (or/c exact-nonnegative-integer? #f) (or/c path? #f))]{ If the node at @scheme[path] below @scheme[root] was copied from some other node, this procedure returns the revision and path it was copied from. Otherwise it returns two @scheme[#f] values. } @defproc[(fs-node-closest-copy [root fs-root?] [path path-string?]) (values (or/c fs-root? #f) (or/c path? #f))]{ Retrieves the revision root and path of the destination of the most recent copy event that caused @scheme[path] to exist where it does in @scheme[root]. Returns two @scheme[#f] values if no such copy exists. } @defproc[(fs-directory-list [root fs-root?] [path path-string?]) (listof path?)]{ Retrieves a list of entries in the directory at @scheme[path] below @scheme[root]. The returned paths are relative to their containing directory. } @defproc[(fs-file-length [root fs-root?] [path path-string?]) exact-nonnegative-integer?]{ Retrieves the length in bytes of the file located at @scheme[path] below @scheme[root]. } @defproc[(fs-file-contents-changed? [src-root fs-root?] [src-path path-string?] [tgt-root fs-root?] [tgt-path path-string?]) boolean?]{ Checks whether the contents of the source at @scheme[src-path] below @scheme[src-root] differ from those of the target at @scheme[tgt-path] below @scheme[tgt-root]. } @deftogether[( @defproc[(fs-node-prop [root fs-root?] [path path-string?] [prop-name symbol?]) (or/c bytes? #f)] @defproc[(set-fs-node-prop! [root fs-root?] [path path-string?] [prop-name symbol?] [value (or/c bytes? #f)]) void?] @defform[#:id set!/fs-node-prop #:literals (set! fs-node-prop) (set! (fs-node-prop root path prop-name) value)] )]{ Retrieves or sets a node property as a binary string. A non-existent property is represented by the value @scheme[#f]. When a property is set to @scheme[#f], it is deleted. } @defproc[(fs-list-node-props [root fs-root?] [path path-string?]) (listof symbol?)]{ Retrieves a list of all properties set on a node. } @section{History} @deftogether[( @defthing[_fs-history ctype?] @defthing[_fs-history/null ctype?] )]{ C pointer type representing file system history objects. A history object represents some event when a file system node is modified or copied, which doesn't necessarily mean that the node's contents or properties change with every history event. } @defproc[(fs-history? [obj any/c]) any]{ Checks whether the given @scheme[obj] is a file system history object. } @defproc[(fs-node-history [root fs-root?] [path path-string?]) fs-history?]{ Retrieves a history object for the node at @scheme[path] below @scheme[root]. } @defproc[(fs-history-prev [history fs-history?] [cross-copies? any/c]) (or/c fs-history? #f)]{ Retrieves the next elder history object preceding @scheme[history]. If @scheme[cross-copies?] is not @scheme[#f], the history chain is followed across copy events. When @scheme[fs-history-prev] is called for the first time on a return value of @scheme[fs-node-history], it may return an object equivalent to the one that was passed in, in case that object itself represents an interesting history event. } @defproc[(fs-history-location [history fs-history?]) (values exact-nonnegative-integer? path?)]{ Retrieves the revision number and the path of the given @scheme[history] event. } @section{Node Contents} @defproc[(fs-open-input-file [root fs-root?] [path path-string?]) input-port?]{ Opens an input port from which the contents of the file at @scheme[path] below @scheme[root] can be read. } @defproc[(fs-open-output-file [root fs-root?] [path path-string?] [#:deltify deltify? any/c #t] [#:base-checksum base-checksum (or/c bytes? #f) #f] [#:result-checksum result-checksum (or/c bytes? #f) #f]) output-stream?]{ Opens an output port to which the new contents of the file at @scheme[path] below @scheme[root] can be written. If @scheme[deltify] is not @scheme[#f], writing data to the stream automatically generated a delta to the previous contents of the file. Otherwise, the new revision stores the full new contents of the file. @scheme[base-checksum] and @scheme[result-checksum] are checksums of the file's content before and after the change. These arguments may be ignored, even if provided, but if provided, they must be correct. } @defproc[(call-with-fs-input-file [root fs-root?] [path path-string?] [proc (-> input-port? any)]) any]{ Calls @scheme[fs-open-input-file] with the @scheme[root] and @scheme[path] arguments and passes the resulting port to @scheme[proc]. When @scheme[proc] returns, the newly opened port is closed. The result of @scheme[proc] is the result of the @scheme[call-with-fs-input-file] call. } @defproc[(call-with-fs-output-file [root fs-root?] [path path-string?] [proc (-> output-port? any)] [#:deltify deltify? any/c #t] [#:base-checksum base-checksum (or/c bytes? #f) #f] [#:result-checksum result-checksum (or/c bytes? #f) #f]) any]{ Calls @scheme[fs-open-output-file] with the @scheme[root], @scheme[path], @scheme[deltify?], @scheme[base-checksum] and @scheme[result-checksum] arguments and passes the resulting port to @scheme[proc]. When @scheme[proc] returns, the newly opened port is closed. The result of @scheme[proc] is the result of the @scheme[call-with-fs-output-file] call. } @defproc[(call-with-fs-input-file* [root fs-root?] [path path-string?] [proc (-> input-port? any)]) any]{ Like @scheme[call-with-fs-input-file], but the newly opened port is closed whenever the dynamic scope of @scheme[call-with-fs-input-file*] is left. } @defproc[(call-with-fs-output-file* [root fs-root?] [path path-string?] [proc (-> output-port? any)] [#:deltify deltify? any/c #t] [#:base-checksum base-checksum (or/c bytes? #f) #f] [#:result-checksum result-checksum (or/c bytes? #f) #f]) any]{ Like @scheme[call-with-fs-output-file], but the newly opened port is closed whenever the dynamic scope of @scheme[call-with-fs-output-file*] is left. } @defproc[(with-fs-input-from-file [root fs-root?] [path path-string?] [thunk (-> any)]) any]{ Like @scheme[call-with-fs-input-file*], but the newly opened port is not passed to @scheme[thunk] but rather installed as the current input port using a parameterization. } @defproc[(with-fs-output-to-file [root fs-root?] [path path-string?] [thunk (-> any)] [#:deltify deltify? any/c #t] [#:base-checksum base-checksum (or/c bytes? #f) #f] [#:result-checksum result-checksum (or/c bytes? #f) #f]) any]{ Like @scheme[call-with-fs-output-file*], but the newly opened port is not passed to @scheme[thunk] but rather installed as the current output port using a parameterization. }