Skip to content

Instantly share code, notes, and snippets.

@intijk
Last active March 29, 2020 09:00
Show Gist options
  • Save intijk/7c37f863d2b2b64005bb8e07a48139d9 to your computer and use it in GitHub Desktop.
Save intijk/7c37f863d2b2b64005bb8e07a48139d9 to your computer and use it in GitHub Desktop.
Download new blender 2.8 from website
#!/usr/bin/env python3
import os
import re
import shutil
import subprocess
#path definition
#install_target: ${HOME}/prog/
#tar_file_path: install_target/blender-2.83-a24f52c51cff-linux64.tar.xz
#blender_foldername: blender-2.83-a24f52c51cff-linux64
#install_folder: install_target/blender_foldername
#install_symlink: install_target/blender -> install_folder
#install_bin: install_symlink/blender
#bin_symlink: ${HOME}/bin/blender -> install_bin
install_target=os.path.join(os.getenv('HOME'), 'prog')
bin_symlink=os.path.join(os.getenv('HOME'), 'bin', 'blender')
requirement_cmd_list=["curl", "axel", "pv"]
def human_readable_size(size, decimal_places=3):
# honor to https://stackoverflow.com/a/43690506/3426137
for unit in ['B','KiB','MiB','GiB','TiB']:
if size < 1024.0:
break
size /= 1024.0
return f"{size:.{decimal_places}f}{unit}"
def print_install_suggestion():
print("Please install all necessary commands: ", end="")
for cmd in requirement_cmd_list:
print("{} ".format(cmd), end="")
print("")
print("")
print("If you are under Ubuntu, use this command to install them all:", end="\n\n")
print("sudo apt install ", end="")
for cmd in requirement_cmd_list:
print("{} ".format(cmd), end="")
print("")
print("")
def check_necessary_installation():
for cmd in requirement_cmd_list:
r=shutil.which(cmd)
if r is None:
print("Command {} not found.".format(cmd), end="\n\n")
print_install_suggestion()
exit(-1)
def get_new_blender_info():
cmd=r'curl -s https://builder.blender.org/download/ | egrep -o "blender-.\...-[^\"]*?-linux[^\"]*?64.tar.[a-z0-9]+"'
print(cmd)
result=os.popen(cmd).readlines()[0].strip()
print(result)
# example blender-.\...-[^\"]*?-linux[^\"]*?64.tar.[a-z0-9]+
r=re.match("^blender-([0-9]+)\.([0-9]+)-([0-f]+)-linux.*64.tar.([a-z0-9]+)$", result)
blender_info={}
if r is None:
return None
else:
blender_info["filename"]=r.group(0)
blender_info["major_version"]=r.group(1)
blender_info["minor_version"]=r.group(2)
blender_info["build_hash"]=r.group(3)
blender_info["compression"]=r.group(4)
return blender_info
def get_existed_blender_info():
blender_info={}
r=shutil.which('blender')
if r is None:
return None
try:
cmd=r"blender --version | grep ^Blender | awk '{print $2}' | awk -F. '{print $1}'"
major_version=os.popen(cmd).readlines()[0].strip()
cmd=r"blender --version | grep ^Blender | awk '{print $2}' | awk -F. '{print $2}'"
minor_version=os.popen(cmd).readlines()[0].strip()
cmd=r"blender --version | grep 'build hash' | awk -F: '{print $2}'"
build_hash=os.popen(cmd).readlines()[0].strip()
except:
return None
if major_version == "" or minor_version=="" or build_hash=="":
return None
else:
blender_info["major_version"]=major_version
blender_info["minor_version"]=minor_version
blender_info["build_hash"]=build_hash
return blender_info
def copy_desktop_file():
print("Copy blender.desktop file to '~/.local/share/applications/")
ret=os.system("cp blender.desktop ~/.local/share/applications/")
if ret!=0:
print("copy command failed with ret code {}, quit script".format(ret))
exit(-1)
print("Copy blender.svg file to '~/.local/share/icons/")
os.system("cp blender.svg ~/.local/share/icons/")
if ret!=0:
print("copy command failed with ret code {}, quit script".format(ret))
exit(-1)
def upgrade_new_version(blender_info):
try:
#download
url="https://builder.blender.org/download/{0}".format(blender_info["filename"])
print("Downloading from {0} into {1}".format(url, install_target))
tar_file_path=os.path.join(install_target, blender_info["filename"])
downloaded_healthy=False
if os.path.isfile(tar_file_path):
print("Expect download file {0} exists".format(tar_file_path))
# no md5sum provided, so use a size check to guess if downloaded file corrupt or not
# https://devtalk.blender.org/t/can-we-provide-md5sum-for-experimental-build/12444
file_size=os.path.getsize(tar_file_path)
if file_size>120*1024*1024:
downloaded_healthy=True
else:
print("Downloaded file size {} smaller than 120M, treat as broken.".format(human_readable_size(file_size)))
if downloaded_healthy:
print("File {0} already downloaded and valid, go uncompress.".format(tar_file_path))
else:
#cmd="wget {0} -P {1} --quiet --show-progress".format(url,install_target)
if os.path.isfile(tar_file_path+".st"):
# axel's status file exist, we could continue download
pass
else:
# axel's status file exist, we need to clean old one
cmd="rm -rf {}".format(tar_file_path)
ret=os.system(cmd)
if ret!=0:
print("Remove old broken tarfile {} failed, quit script".format(tar_file_path))
exit(-1)
cmd="axel {0} -o {1} -a".format(url,install_target)
ret=os.system(cmd)
if ret!=0:
print("Download command exit with code {}, quit script.".format(ret))
exit(-1)
#uncompress
os.chdir(install_target)
cmd="basename -s .tar.{0} {1}".format(blender_info['compression'],blender_info["filename"])
blender_folder_name=os.popen(cmd).readlines()[0].strip()
if os.path.isdir(blender_folder_name):
print("Folder {0} already existed, skip uncompress.".format(blender_folder_name))
else:
if blender_info['compression'] == 'xz':
cmd="pv {0} | tar xJf -".format(tar_file_path)
elif blender_info['compression']== 'bz2':
cmd="pv {0} | tar xjf -".format(tar_file_path)
elif blender_info['compression']== 'gz':
cmd="pv {0} | tar xf -".format(tar_file_path)
else:
print("Unknown compression format {}".format(blender_info['compression']))
exit(-1)
print("Uncompressing {0} into {1}...".format(tar_file_path, blender_folder_name))
ret=os.system(cmd)
if ret!=0:
print("Uncompress command exit with code {}, quit script.".format(ret))
exit(-1)
# get folder name
print("Create symlink blender -> {}".format(blender_folder_name))
os.system("rm -rf blender; ln -sf {0} blender".format(blender_folder_name))
os.chdir("blender")
copy_desktop_file()
home_folder=os.getenv("HOME")
bin_folder=os.path.join(home_folder, "bin")
os.chdir(bin_folder)
print("Create symlink ~/bin/blender -> ~/prog/blender, with cwd {}".format(os.getcwd()))
os.system("rm -rf blender; ln -sf ~/prog/blender/blender blender")
install_symlink=os.path.join(install_target,"blender")
install_bin=os.path.join(install_symlnk,"blender")
sym_folder=os.path.basename(bin_symlink)
ret=os.system("rm -rf {}; ln -sf {} {}".format(bin_symlink, install_bin, bin_symlink))
if ret!=0:
print("WARNING: create install symlink with code {}, will continue.", ret)
except:
return False
return True
def clean_old_version(blender_info):
blender_info["filename"]
cmd="basename -s .tar.{0} {1}".format(blender_info['compression'], blender_info["filename"])
blender_folder_name=os.popen(cmd).readlines()[0].strip()
os.chdir(install_target)
for f in os.listdir(install_target):
if f.startswith("blender") and f!="blender" and f!=blender_folder_name and f!=blender_info["filename"]:
print("Removing old version file {0}".format(f))
os.system("rm -rf {0}".format(f))
def main():
check_necessary_installation()
new_blender_info=get_new_blender_info()
old_blender_info=get_existed_blender_info()
if new_blender_info is None:
print("Get new blender info failed, do not perform update")
elif old_blender_info is not None and new_blender_info["major_version"] == old_blender_info["major_version"] \
and new_blender_info["minor_version"]==old_blender_info["minor_version"] \
and new_blender_info["build_hash"]==old_blender_info["build_hash"]:
print("Already newest version", old_blender_info)
clean_old_version(new_blender_info)
else:
print("New version found")
print("Old version:", old_blender_info)
print("New version:", new_blender_info)
if upgrade_new_version(new_blender_info):
clean_old_version(new_blender_info)
if __name__=="__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment