Last active
March 29, 2020 09:00
-
-
Save intijk/7c37f863d2b2b64005bb8e07a48139d9 to your computer and use it in GitHub Desktop.
Download new blender 2.8 from website
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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