* Problem with code snippet

For users to report plugin bugs and request plugin enhancements; and for authors to test new/new versions of plugins, and to discuss plugin development (in the Programming Technicalities sub-forum). If you want advice on choosing or using a plugin, please ask in General Usage or an appropriate sub-forum.
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: Problem with code snippet

Post by ColeValleyGirl »

If you could add zip that would be great.

Does

Code: Select all

    local zfile = assert(zip.open(zipPath.."\\"..zipFilename),"Failed to open zip file "..zipPath.."\\"..zipFilename) --open the zip file for processing
address the error handling requirement?

I'm not a fan of offline help because I shall eventually fall off the twig and want to leave people with something they can continue to use when my hosting arrangements go down the river... and I want to use help html which the FHUG wiki can't support.

Once tested, I shall post it as a separate code snippet (as it has different restrictions and functionality to the other set).
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Problem with code snippet

Post by tatewise »

Have added the zip download.

I was thinking more along the lines of:

Code: Select all

if zfile then
    --get the identity of any subdirectories and create them in destinationPath
    for loops ...
    zfile:close()
else
    fhMessageBox( err )
end
BTW: I have spotted that none of those "\\".. are needed. Just use zipPath..zipFilename
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: Problem with code snippet

Post by ColeValleyGirl »

Any reason you prefer that approach? I would expect to do the error handling before the snippet is invoked (customised to the calling plugin), so the assert statement is just belt and braces -- i.e. not call ExtractZip unless I knew the zip file existed.

I get errors without the \\ -- which specific ones do you think are unnecessary?
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Problem with code snippet

Post by tatewise »

Yes, my script is inside the function ExtractZip snippet the same as your assert(...).
I prefer the more user friendly style of fhMessageBox instead of the scarier Plugin Error message.
Also it uses the actual error message returned by zip.open that may be more explicit than Failed to open zip file.
But as you say, it should only be a backstop, so I have no strong preference.

The "\\".. depend on exactly what is provided in zipPath and destinationPath.
I used different paths that had trailing \\ but I see now your original script does not.
So if the "\\".. are omitted you get an error if the \\ are needed.
Or if the "\\".. are included when not needed you get double \ in the path error message.

The 'perfect' solution is to add zipPath = zipPath:gsub("\\$","") and similar for destinationPath and retain the "\\"..
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Problem with code snippet

Post by tatewise »

I have looked at the ExtractZip snippet again and below is my proposed script.
It adds the gsub("\\$","") to strip optional trailing backslashes from paths.
It has only one iteration loop for file in zfile:files() do that both creates new paths and copies files.
Was there a reason why your original needed to have two loops?

Code: Select all

function ExtractZip(zipPath, zipFilename, destinationPath)

    zipPath = zipPath:gsub("\\$","")
    destinationPath = destinationPath:gsub("\\$","")
    local zfile = assert(zip.open(zipPath.."\\"..zipFilename),"Failed to open zip file "..zipPath.."\\"..zipFilename) --open the zip file for processing

    local function CopyFile(file)
        local currFile, err = zfile:open(file.filename) --open a file within the zipfile
        local currFileContents = currFile:read("*a") -- read entire contents of current file
        local hBinaryOutput = io.open(destinationPath .."\\".. file.filename, "wb") --open an outputfile
        -- write current file inside zip to a file outside zip
        if hBinaryOutput then
            hBinaryOutput:write(currFileContents) --write the new file as a copy of the file within the zipfile
            hBinaryOutput:close() --close the new file
        end
        currFile:close() --close the file within the zipfile
    end

    -- iterate through each file inside the zip file
    for file in zfile:files() do
        local newdir = path.dirname(file.filename)
        if not path.exists(destinationPath.."\\"..newdir) then dir.makepath(destinationPath.."\\"..newdir) end
        if path.basename(file.filename) ~= "" then CopyFile(file) end
    end

    zfile:close()

end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: Problem with code snippet

Post by ColeValleyGirl »

Re two loops, it was easier for testing -- one is fine.

One thing I suspect (and haven't had a chance to verify): the code is losing the case of the unzipped files/directories.

Edited: Yes, it's converting names to lower case.
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Problem with code snippet

Post by tatewise »

Solution is to use lfs.mkdir in place of dir.makepath but it needs to be presented with one nested path at a time.

The copied files do retain their case.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
ColeValleyGirl
Megastar
Posts: 5465
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: Problem with code snippet

Post by ColeValleyGirl »

I can live with it at present as the case for the directory doesn't matter, but I will make a note to revisit when I have some time.
User avatar
tatewise
Megastar
Posts: 28341
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: Problem with code snippet

Post by tatewise »

This will do it:

Code: Select all

    -- iterate through each file inside the zip file
    for file in zfile:files() do
        local newdir = path.dirname(file.filename)
        if not path.exists(destinationPath.."\\"..newdir) then
            local destPath = destinationPath
            for nextdir in newdir:gmatch("[^/]+") do
                destPath = destPath.."\\"..nextdir
                lfs.mkdir(destPath)
            end
        end
        if path.basename(file.filename) ~= "" then CopyFile(file) end
    end
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Post Reply