Documentation
¶
Overview ¶
Package hrx provides human-readable archive utilities
Introduction ¶
This package implements support for reading, manipulating and writing "human-readable archive" (`.hrx`) files. These archives are like `tar` archives except that they only store plain text files and the internal structure is easily editable by humans.
Here's the summary from the official specification:
This is a specification for a plain-text, human-friendly format for defining multiple virtual text files in a single physical file, for situations when creating many physical files is undesirable, such as defining test cases for a text format.
Index ¶
Constants ¶
const ( // OpExtracted is the ReporterFn note used when a file is extracted OpExtracted = "extracted" // OpCreated is the ReporterFn note used when creating a directory OpCreated = "created" // OpSkipped is the ReporterFn note used when a file is skipped from // extraction because it was not included with the other pathnames // given for specific extraction OpSkipped = "skipped" // OpDeleted is the ReporterFn note used when a file is deleted from // an Archive instance OpDeleted = "deleted" // OpAppended is the ReporterFn note used when a file is appended to // an Archive instance during Archive.Set OpAppended = "appended" // OpUpdated is the ReporterFn note used when a file is updated within // an Archive instance during Archive.Set OpUpdated = "updated" // OpBoundary is the ReporterFn note used when the Archive boundary is // changed. Note that all nested archives also emit this report when // the top-level Archive.SetBoundary call is made. The top-level report // will have an empty pathname argument OpBoundary = "boundary" )
The following constants are the ReporterFn note strings used when reporting progress
const (
// DefaultBoundary is the boundary size for New archives created
DefaultBoundary = 5
)
Variables ¶
var ( ErrMalformedInput = errors.New("malformed input") ErrSequentialComments = errors.New("sequential comments") ErrBadFileEntry = errors.New("bad file entry") ErrDirectoryHasContents = errors.New("directory has contents") ErrDuplicatePath = errors.New("duplicate path") ErrFileAsParentDir = errors.New("file as parent directory") )
HRX specification errors
var ( ErrNotFound = errors.New("pathname not found") ErrEmptyArchive = errors.New("empty archive") ErrNotAnArchive = errors.New("not an archive (.hrx)") ErrBadArchiveHeader = errors.New("bad archive header") ErrBadBoundary = errors.New("bad archive boundary") ErrNoSpaceBeforePath = errors.New("no space before pathname") ErrInvalidUnicode = errors.New("contains invalid unicode") ErrStartsWithDirSep = errors.New("pathname starts with a path separator") ErrInvalidCharRange = errors.New("pathname contains invalid ascii") ErrContainsColon = errors.New("pathname contains a colon") ErrEscapeCharacter = errors.New("pathname contains escape characters") ErrContainsRelPath = errors.New("pathname contains relative names (//, . or ..)") )
Specific error messages
var ( // DefaultFileMode is the os.FileMode setting used to extract files DefaultFileMode os.FileMode = 0640 )
var (
ErrDstIsFile = errors.New("destination directory is a file")
)
General package errors
Functions ¶
This section is empty.
Types ¶
type Archive ¶
type Archive interface {
// FileName is the filename given when constructing this Archive instance
FileName() (filename string)
// SetBoundary changes this archive's boundary to the size given and if
// there are any nested archives within this archive, they are all updated
// with nested increments of the size given
SetBoundary(size int) (err error)
// GetBoundary returns this archive's boundary size (number of equal signs
// within the HRX headers)
GetBoundary() (size int)
// SetComment specifies a general comment for this archive
SetComment(comment string)
// GetComment returns the general comment for this archive, if one exists
GetComment() (comment string, ok bool)
// DeleteComment removes the general comment for this archive
DeleteComment()
// Set adds or overwrites pathname with the given body and comment. Empty
// comments are ignored. Set may return an error if another HRX file is
// being set and a parsing error happened while adjusting the nested
// archive's boundary size
Set(pathname, body, comment string) (err error)
// Get returns the body and any comment for the given pathname
Get(pathname string) (body, comment string, ok bool)
// Delete removes the pathname entry
Delete(pathname string)
// Entry returns a read-only interface for a specific pathname. Returns
// nil if there is no entry for the specified pathname
Entry(pathname string) Entry
// Len returns the number of entries stored within this archive. Len does
// not recurse into nested HRX files and does not include any general
// comment for this archive
Len() (entries int)
// List returns a list of all entry pathnames, in the order they are found
// within this archive. List does not recurse into nested HRX files
List() (pathnames []string)
// Entries returns a list of all file and directory entries within this
// Archive instance. Entries does not recurse into embedded HRX Archive
// files
Entries() (entries []Entry)
// ParseHRX looks for the entry associated with the given pathname and if
// the pathname has the `.hrx` extension, attempts to parse the contents
// into a new Archive instance
ParseHRX(pathname string) (parsed Archive, err error)
// String returns the actual contents of this archive
String() (archive string)
// WriteFile takes the String of this Archive and writes the contents to
// the local filesystem, at the path given. WriteFile will attempt to
// make all parent directories for the destination file
WriteFile(destination string) (err error)
// ExtractTo extracts all of this Archive's entries to their individual
// files on the local filesystem. If any pathnames are also given then
// only those will be extracted. If no pathnames are given, all files are
// extracted
ExtractTo(destination string, pathnames ...string) (err error)
// SetReporter configures the internal event reporter function. This is
// only really useful for user-interfaces requiring notifications whenever
// an operation is performed
SetReporter(fn ReporterFn)
}
Archive is a computer-readable parsing of a human-readable archive
func ParseData ¶
ParseData parses the given data and associates the resulting Archive with the filename given
type Entry ¶
type Entry interface {
// IsComment reports true when the boundary pathname is empty
IsComment() bool
// IsFile reports true when the boundary pathname is not empty and does not
// end with a directory separator
IsFile() bool
// Size returns zero and false for directories and for comments and
// files, returns the number of bytes and true
Size() (size int, ok bool)
// IsDir reports true when the boundary pathname is not empty and ends with
// a directory separator
IsDir() bool
// IsHRX reports true when the boundary pathname is not empty and ends with
// a `.hrx` extension
IsHRX() bool
// ParseHRX checks if this entry IsHRX and parses the body content into a
// new Archive instance. Note that modifying the parsed Archive will not
// update this specific entry's body content
//
// Example of modifying and saving a nested Archive instance:
//
// a := ParseData("example.hrx", ...)
// if entry := a.GetEntry("nested.hrx"); entry != nil {
// if b, err := entry.ParseHRX(); err != nil {
// ... handle error ...
// } else {
// b.Set("filename", "new contents", "")
// a.Set("nested.hrx", b.GetBody(), b.GetComment())
// if err = a.WriteFile("example.hrx"); err != nil {
// ... handle error ...
// }
// }
// }
//
ParseHRX() (a Archive, err error)
// GetPathname returns the pathname from the HRX header line for this entry
GetPathname() (pathname string)
// GetBody returns the body contents of this HRX entry
GetBody() (body string)
// GetComment returns the comment associated with this HRX entry
GetComment() (comment string)
// String is the complete boundary pathname body newline contents for this
// entry, even if it is itself another .hrx file and includes any preceding
// comment
String() (data string)
}
Entry is a read-only interface for a specific HRX entry
type Error ¶
type Error struct {
// File is the filename given to ParseData or ParseFile
File string
// Base is the related HRX error message
Base error
// Wrap is the specific error message
Wrap error
// Line is the line number of the archive where this error has occurred
Line int
}
Error is the type for all error instances returned from this package
type ReporterFn ¶
type ReporterFn func(archive, pathname, note string, argv ...interface{})
ReporterFn is the function signature for Archive progress reporting
type Scanner ¶
type Scanner struct {
scanners.LineScanner
// contains filtered or unexported fields
}
Scanner is a line-reading text scanner for parsing HRX archive contents
func NewScanner ¶
NewScanner constructs a new Scanner instance
func (*Scanner) Get ¶
func (s *Scanner) Get() (content string, line, boundary int, pathname string, header bool, err error)
Get returns the current Scan results
content is the entire line read as-is line is the current line number boundary is the number of equal signs in the parsed HRX `<====>` boundary pathname is the pathname component of the HRX boundary line header reports if the boundary and pathname values are valid err reports any error detected on this line