Old 03-17-2020, 09:28 AM   #1
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default Could someone with OSX/Linux run this code and tell me if it works?

code on post #12

Code:
function UnzipReaperTheme(ReaperThemeZip, tempfolder)
  local cmd = 'read a; read d; unzip -qq -o "$a" *.ReaperTheme "$d"'
  local pipe = io.popen(cmd, 'w')
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(tempfolder .. "\n")
  state = ({pipe:close()})[3]
  return state == 0 and true or false
end

local ColorThemespath = reaper.GetResourcePath() .."\\ColorThemes\\"
local theme = ColorThemespath .. "Default_5.0.ReaperThemeZip"
local TempFolder = string.match(reaper.time_precise()*100, "(%d+)%.")
success = UnzipReaperTheme( theme, TempFolder )
if success then reaper.CF_ShellExecute (ColorThemespath)

If it worked you should see in your ColorThemes foldes a new directory (with a number as its name) and inside there is this file: Default_5.0_unpacked.ReaperTheme


Thanks!

Last edited by amagalma; 03-21-2020 at 02:41 PM.
amagalma is online now   Reply With Quote
Old 03-17-2020, 12:05 PM   #2
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,083
Default

The last line of code was missing an "end" on last if statement.

When I added the "end" , the script was error-free, but no changes were made in my Color Themes folder. I checked, and I do have "Default_5.0.ReaperThemeZip" installed.

I hope this helps.
__________________
Cheers,
Andrew K
v6.03+dev0114 - January 14 2020 • Mac 10.12.+ • i7 Quad 2.9GHz • 24GB
Thonex is offline   Reply With Quote
Old 03-17-2020, 02:49 PM   #3
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

Thank you! Could you try this and tell me if it worked this time??:

Code:
function UnzipReaperTheme(ReaperThemeZip, tempfolder)
  local path = ReaperThemeZip:match("(.*/)") .. tempfolder
  local cmd = 'read p; read a; read d; mkdir "$p"; unzip -o "$a" *.ReaperTheme -d "$d"'
  local pipe = io.popen(cmd, 'w')
  pipe:write(path .. "\n")
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(tempfolder .. "\n")
  state = ({pipe:close()})[3]
  return state == 0 and true or false
end

local ColorThemespath = reaper.GetResourcePath() .."\\ColorThemes\\"
local theme = ColorThemespath .. "Default_5.0.ReaperThemeZip"
local TempFolder = string.match(reaper.time_precise()*100, "(%d+)%.")
success = UnzipReaperTheme( theme, TempFolder )
if success then reaper.CF_ShellExecute (ColorThemespath) end
amagalma is online now   Reply With Quote
Old 03-17-2020, 03:06 PM   #4
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 3,060
Default

Linux and macOS use regular slashes as directory separator. "\\ColorThemes\\​" must be "/ColorThemes/".

The value of the -d (destination) option is just the random number currently. It should be an absolute path, otherwise it attempts to create it in the current working directory (which in REAPER is usually the root, not user-writable).

*.ReaperTheme tries to match a file in the current working directory, not an entry in the zip file. It should be Default_5.0_unpacked.ReaperTheme.

Also unzip creates the directory itself so mkdir is unnecessary.

Code:
function UnzipReaperTheme(ReaperThemeZip, file, tempfolder)
  local pipe = io.popen('read a; read f; read d; unzip -o "$a" "$f" -d "$d"', 'w')
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(file .. "\n")
  pipe:write(tempfolder .. "\n")
  return ({pipe:close()})[3] == 0
end

local ColorThemespath = reaper.GetResourcePath() .."/ColorThemes/"
local theme = ColorThemespath .. "Default_5.0.ReaperThemeZip"
local TempFolder = string.match(reaper.time_precise()*100, "(%d+)%.")
TempFolder = theme:match("(.*/)") .. TempFolder
success = UnzipReaperTheme( theme, 'Default_5.0_unpacked.ReaperTheme', TempFolder )
if success then reaper.CF_ShellExecute (TempFolder) end

Last edited by cfillion; 03-17-2020 at 03:28 PM.
cfillion is offline   Reply With Quote
Old 03-17-2020, 03:15 PM   #5
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

Thank you! But what if I don't know the exact name of the file that I want to extract? Let's say that I want to extract all files with a ReaperTheme extension (*.ReaperTheme). How can this be done? Also, if I don't put the -d will the directory I pass be relative to the zip's directory?
amagalma is online now   Reply With Quote
Old 03-17-2020, 03:16 PM   #6
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,083
Default

Quote:
Originally Posted by amagalma View Post
Thank you! Could you try this and tell me if it worked this time??:

Code:
function UnzipReaperTheme(ReaperThemeZip, tempfolder)
  local path = ReaperThemeZip:match("(.*/)") .. tempfolder
  local cmd = 'read p; read a; read d; mkdir "$p"; unzip -o "$a" *.ReaperTheme -d "$d"'
  local pipe = io.popen(cmd, 'w')
  pipe:write(path .. "\n")
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(tempfolder .. "\n")
  state = ({pipe:close()})[3]
  return state == 0 and true or false
end

local ColorThemespath = reaper.GetResourcePath() .."\\ColorThemes\\"
local theme = ColorThemespath .. "Default_5.0.ReaperThemeZip"
local TempFolder = string.match(reaper.time_precise()*100, "(%d+)%.")
success = UnzipReaperTheme( theme, TempFolder )
if success then reaper.CF_ShellExecute (ColorThemespath) end
It still didn't work, but I can confirm that cfillon's script does work.

You guys rock!

Cheers,

Andrew K
__________________
Cheers,
Andrew K
v6.03+dev0114 - January 14 2020 • Mac 10.12.+ • i7 Quad 2.9GHz • 24GB
Thonex is offline   Reply With Quote
Old 03-17-2020, 03:23 PM   #7
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 3,060
Default

Quote:
Originally Posted by amagalma View Post
But what if I don't know the exact name of the file that I want to extract? Let's say that I want to extract all files with a ReaperTheme extension (*.ReaperTheme).
unzip does support globbing (*.ReaperTheme). The issue before was that *.ReaperTheme was not in quotes, so it was the shell that was seeing the *, not unzip.

Code:
function UnzipReaperTheme(ReaperThemeZip, tempfolder)
  local pipe = io.popen('read a; read d; unzip -o "$a" "*.ReaperTheme" -d "$d"', 'w')
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(tempfolder .. "\n")
  return ({pipe:close()})[3] == 0
end
Quote:
Originally Posted by amagalma View Post
Also, if I don't put the -d will the directory I pass be relative to the zip's directory?
Without -d "$d" unzip would attempt (and fail) to extract the file in the current directory (usually / in REAPER). "$d" alone would mean another file to extract.

Last edited by cfillion; 03-17-2020 at 03:33 PM.
cfillion is offline   Reply With Quote
Old 03-17-2020, 03:46 PM   #8
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

Thank you very much!


Is this ok?


Code:
function UnzipReaperTheme(ReaperThemeZip, relativetempfolder)
  local TempFolder = ReaperThemeZip:match("(.*/)") .. relativetempfolder
  local ReaperTheme
  local pipe = io.popen('read a; read d; unzip -oqq "$a" "*.ReaperTheme" -d "$d"', 'w')
  pipe:write(ReaperThemeZip .. "\n")
  pipe:write(TempFolder .. "\n")
  local state = ({pipe:close()})[3]
  if state == 0 then
    ReaperTheme = reaper.EnumerateFiles( TempFolder, 0 )
  else
    return
  end
  return TempFolder .. "/" .. ReaperTheme -- full path to extracted ReaperTheme file
end

local ColorThemespath = reaper.GetResourcePath() .. "/ColorThemes/"
local theme = ColorThemespath .. "Default_5.0.ReaperThemeZip"
local relativetempfolder = string.match(reaper.time_precise()*100, "(%d+)%.")
fullpath = UnzipReaperTheme(theme, relativetempfolder)
if reaper.file_exists(fullpath) then reaper.ShowConsoleMsg("Yay!") end

I don't want any info displayed that is the -oqq for. Is the whole thing right?
amagalma is online now   Reply With Quote
Old 03-17-2020, 03:55 PM   #9
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 3,060
Default

Yes!

-o disables prompting if the file was already extracted to the specified directory. -q/-qq disables most of unzip's output. (Since there is no cmd.exe window poping up on Linux and macOS, it's invisible to the user either way (unzip's output is only visible if the user launched REAPER from a terminal).)
cfillion is offline   Reply With Quote
Old 03-17-2020, 04:02 PM   #10
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

I see! Thank you!


Last thing. Is this ok in order to update the .ReaperTheme file inside the .ReaperThemeZip?
Code:
function UpdateReaperThemeZip(ReaperThemeZip, UnpackedTheme)
  -- full path for both files
  if not reaper.file_exists( ReaperThemeZip ) or not reaper.file_exists( UnpackedTheme ) then return end
  local pipe, state
  local pipe = io.popen('read a; read u; zip -j "$a" "$u"', 'w')
  pipe:write(ReaperThemeZip .. '\n')
  pipe:write(UnpackedTheme .. '\n')
  state = ({pipe:close()})[3]
  return state == 0 and true or false -- returns if succeded or not
end

Last edited by amagalma; 03-17-2020 at 04:17 PM.
amagalma is online now   Reply With Quote
Old 03-18-2020, 07:29 AM   #11
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

Code:
zip -j fullpathofarchive/archive.zip fullpathoffile/filetobereplaced

Is this the correct syntax to replace a file ("filetobereplaced") in a zip archive ("archive.zip") , if that file is not inside a directory in the zip?
amagalma is online now   Reply With Quote
Old 03-21-2020, 02:26 PM   #12
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

This is the full function to extract a ReaperTheme. Works fine on Windows but possibly fails on OSX. Any ideas why? Everything looks ok to me :/

Code:
-- Function to extract theme --
local Win = string.match(reaper.GetOS(), "Win" ) == "Win"
local sep = Win and "\\" or "/"

function UnzipReaperTheme(ReaperThemeZip)
  ReaperThemeName = ReaperThemeZip:match([[.*[\/]([^\/]-)Zip$]])
  local TempFolder = string.match(reaper.time_precise()*100, "(%d+)%.") -- will be a random number in the same dir as the ReaperThemeZip
  local cmd, FullTempFolder, script_path
  local ColorthemePath = ResourcePath .. sep .. "ColorThemes" .. sep
  if Win then -- (use PowerShell .NET methods)
    FullTempFolder = ReaperThemeZip:match("(.*\\)") .. TempFolder
    local script =
    [[$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zipFilePath = "]] .. ReaperThemeZip .. '"\n$extractPath = "' .. FullTempFolder .. '"\n' ..
[[$zip = [System.IO.Compression.ZipFile]::OpenRead($zipFilePath)
[System.IO.Directory]::CreateDirectory($extractPath)
$zip.Entries | Where-Object Name -like *.ReaperTheme | ForEach-Object{[System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, "$extractPath\$($_.Name)", $true)}
$zip.Dispose()]]
    script_path = ResourcePath .. sep .. "UnzipReaperTheme.ps1"
    local file = io.open(script_path, "w+")
    file:write(script)
    file:close()
    cmd = "powershell.exe -ExecutionPolicy Bypass " .. script_path, 'w'
  else -- OSX/LINUX (use unzip)
    cmd = 'read a; read d; unzip -oqq "$a" "*.ReaperTheme" -d "$d"', 'w'
    FullTempFolder = ReaperThemeZip:match("(.*/)") .. TempFolder
  end
  local pipe = io.popen(cmd)
  if not Win then -- pass values to unzip (OSX/Linux)
    pipe:write(ReaperThemeZip .. '\n')
    pipe:write(FullTempFolder .. '\n')
  end
  local state = ({pipe:close()})[3]
  -- Delete temporary PowerShell script
  if Win then os.remove(script_path) end
  if state == 0 then
    local ReaperTheme = reaper.EnumerateFiles( FullTempFolder, 0 )
    -- Move extracted theme to ColorThemes directory and name it as the zipped file
    os.rename(FullTempFolder .. sep .. ReaperTheme, ColorthemePath .. ReaperThemeName)
    -- Delete temporary folder
    if Win then
      os.execute('rd /s/q "'.. FullTempFolder ..'"')
    else
      ok = os.remove(FullTempFolder)
      if not ok then os.execute('rm -rd "'..path_to_dir..'"')
        reaper.ShowConsoleMsg("Failed to delete temp directory in ColorThemes")
      end
    end
    return ColorthemePath .. ReaperThemeName -- full path to extracted ReaperTheme file
  else
    local msg
    if Win then
      msg = "Possibly your Windows version does not have PowerShell?"
    else
      msg = "Check that you have 'unzip' installed."
    end
    reaper.MB( "Failed to unzip the ReaperThemeZip file. " .. msg, "Something went wrong...", 0 )
    return
  end
end

Last edited by amagalma; 03-21-2020 at 02:41 PM.
amagalma is online now   Reply With Quote
Old 03-22-2020, 10:43 AM   #13
cfillion
Human being with feelings
 
cfillion's Avatar
 
Join Date: May 2015
Location: Québec, Canada
Posts: 3,060
Default

I can't try it right now but it looks like io.popen(cmd) is opening the process in read mode instead write. It should be io.popen(cmd, 'w').

Code:
$zipFilePath = "]] .. ReaperThemeZip .. '"\n$extractPath = "' .. FullTempFolder .. '"\n' ..
This should use pipe:write(...) + Read-Host instead of injecting arbitrary data directly into the script (unreliable/dangerous).

Code:
if not ok then os.execute('rm -rd "'..path_to_dir..'"')
There is no path_to_dir variable in the code but same as above. On macOS/Linux paths can contain quotes (any characters beside / and NULL are allowed). -r (recursive) already implies the -d option.
cfillion is offline   Reply With Quote
Old 03-22-2020, 05:07 PM   #14
amagalma
Human being with feelings
 
Join Date: Apr 2011
Posts: 1,699
Default

Thank you very much cfillion!! Once again you saved the day!


Now that you have pointed me to the mistakes, the mistakes in the code are striking to me! How could I have missed this!? But before, I was looking again and again at the code and I could not see them! :/
amagalma is online now   Reply With Quote
Old 03-22-2020, 06:58 PM   #15
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,083
Default

Quote:
Originally Posted by amagalma View Post
.
.
.

Now that you have pointed me to the mistakes, the mistakes in the code are striking to me!
.
.
.
Welcome to my life
__________________
Cheers,
Andrew K
v6.03+dev0114 - January 14 2020 • Mac 10.12.+ • i7 Quad 2.9GHz • 24GB
Thonex is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 11:52 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.