jxxcarlson/elm-tar/3.0.12

NOTE: the latest version is 4.0.0

Elm-Tar

With this package you can both create and extract tar archives using

   createArchive List (Metadata, Data) -> Bytes

   extractArchive : Bytes -> List ( MetaData, Data )

Types

The Data type discriminates between string and binary data:

type Data
    = StringData String
    | BinaryData Bytes

The MetaData type is complex and reflects the official tar specification:

type alias MetaData =
    { filename : String
    , mode : Mode
    , ownerID : Int
    , groupID : Int
    , fileSize : Int
    , lastModificationTime : Int
    , linkIndicator : Link
    , linkedFileName : String
    , userName : String
    , groupName : String
    , fileNamePrefix : String
    , typeFlag : Ascii
    }

The mode carries Unix file permissions, e.g., 644. The fileNamePrefix can be thought of as the name of the folder/directory in which the files to be processed live.

Because filling out this record is something a pain, a defaultMetadata : MetaData value is provided. It can be modified as needed.

Example

To give a simple example, we make define some binary data and check that it is what we think it is:

> import Hex                  -- from jxxcarlson/hex
> import Bytes.Encode as E    -- from elm/bytes

> null = E.encode (E.unsignedInt8 0)
<1 bytes> : Bytes.Bytes

> bytes = Hex.toBytes "0001A1FF" |> Maybe.withDefault null
<4 bytes> : Bytes.Bytes

> Hex.fromBytes bytes
"0001A1FF" : String

Next, we create an archive consisting of one text file and one binary file:

import Tar exposing(..)

metadata = { defaultMetadata | filename = "test123.txt" }

text = "This is a test (ho ho ho).\nIt is a frabjous day!"

metadata2 = { defaultMetadata | filename = "foo.binary" }

> archive = createArchive [ ( metadata, StringData text ), ( metadata2, BinaryData bytes ) ]
<3072 bytes> : Bytes.Bytes

File.Download.bytes "test.tar" "application/x-tar" archive
<internals> : Cmd msg -- You can't do this one in the repl.

Metadata notes

(1) There is an unresolved problem of how to properly encode the metadata of text files so that extractArchive knows to decode the content as a string. At the moment, archived files whose content is to be decoded as a string are recognized by their file extension. The admissible text files have extension in the list

[ "text", "txt", "tex", "csv" ]

This is an unsatisfactory solution, but at the moment, I don't know how to get around it.

(2) The fileNamePrefix in the metadata is the name of the folder into which the files willl be decoded.

Improvements

As Runar Furenes (@ruf) pointed out to me, there was an asymmetry in the way metadata was treated: not the same for extractArchive as for createArchive. This sort of thing is almost always a sign of bad design and poor esthetic judgement. I've fixed it, so the type signatures are now as above. Much better!

Testing

Well, we really do need some tests, as @ruf also noted. [Thanks Runar!] We do have some rudimentary ones now:

   > import Tests exposing(..)

   > checkListAsString stringTestData
     [(0,True),(1,True),(2,True)]

   > checkListAsBinary binaryTestData
   > [(0,True),(1,True)] : List ( Int, Bool )

See the module Test to see what these results mean. Basically, (k, True) means that the k-th test passes. More detalis in Tests.md.

Demo app

For a demo, run elm make Main.elm in /examples, then click on the resulting index.html file.

References

I've used https://en.wikipedia.org/wiki/Tar_(computing) as my reference for the tar file format.

Credits

Many thanks to Folkert deVries for important bug fix (handling of unicode characters)