Created
March 18, 2017 20:30
-
-
Save pscheid92/bd1b665003d2bf83a795408d97eae4aa to your computer and use it in GitHub Desktop.
cron.daily script for installing RStudio daily build on Fedora
This file contains hidden or 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 subprocess | |
import sys | |
import urllib.request | |
# Global configuration dictionary | |
# | |
# page_url: Url to download page from rstudio.org | |
# dest_file: Name of file after download | |
# filter_str: String to find lines with download link | |
options = { | |
"page_url": "https://www.rstudio.org/download/daily/desktop/fedora64/", | |
"dest_file": "rstudio.rpm", | |
"filter_str": "rstudio-dailybuilds" | |
} | |
def abort_if_not_root(): | |
""" | |
Abort program with error message if user is not root. | |
""" | |
if os.getuid() != 0: | |
print("Please run this script as root user!", file=sys.stderr) | |
sys.exit(1) | |
def extract_download_link(url, filter_str): | |
""" | |
Extract download urls from RStudios website. | |
Loads the daily downloads webpage from rstudio.org and search for | |
the first download link on the page. Since the page is usually sorted | |
this method finds the link to the recent version. | |
:param url: URL to RStudios download page. | |
:param filter_str: Pattern to find lines with download urls. | |
""" | |
# Download from webpage | |
print("Request webpage from server ...") | |
with urllib.request.urlopen(url) as handle: | |
lines = handle.readlines() | |
# Decode and filter | |
print("Decode and filter lines ...") | |
lines = list(map(bytes.decode, lines)) | |
lines = list(filter(lambda x: filter_str in x, lines)) | |
# Extract download link | |
res = re.search(r'<a href=["\'](.*)["\']>rstudio.*rpm</a>', lines[0]) | |
if res: | |
print("Found download link ...") | |
return res.groups()[0] | |
else: | |
print("Cannot find download link. Exit ...") | |
sys.exit(1) | |
def get_local_version(): | |
""" | |
Reading out the current version installed. | |
This function runs the rpm command to find the version of the installed | |
RStudio rpm package. If the current version cannot be found, return 0.0.0 | |
as a dummy version. | |
:returns: Current version as string. | |
""" | |
# Running rpm query to get the current rstudio package version | |
print("Request local version ...") | |
res = subprocess.run( | |
['rpm', '-q', 'rstudio'], | |
universal_newlines=True, | |
stdout=subprocess.PIPE | |
) | |
# Use regex to split the version information | |
res = re.search(r"(\d+\.\d+\.\d+)", res.stdout) | |
if res: | |
# Found version, return it | |
print("Found local version ...") | |
return res.group() | |
else: | |
# Haven't found version, return dummy version 0.0.0 | |
print("Cannot find local version. Is RStudio not installed yet?") | |
return("0.0.0") | |
def get_remote_version(link): | |
""" | |
Extract remote version from download link. | |
:param link: Previously loaded download link from rstudio.org. | |
:returns: Version as string. | |
""" | |
# Use regex to find version number in link | |
print("Request remote version ...") | |
res = re.search(r'\d+\.\d+\.\d+', link) | |
if res: | |
# If number is found, return it. | |
print("Found remote version ...") | |
return res.group() | |
else: | |
# Else, abort the program. | |
print("Cannot find remote version. Exit ...") | |
sys.exit(1) | |
def compare_versions(version_a_str, version_b_str): | |
""" | |
Compares two given semantic versions. | |
:param version_a_str: First version as string. | |
:param version_b_str: Second version as string. | |
:returns: True if the first version is really smaller than the second one. | |
""" | |
# Split the version, convert it to int and save it in tuples | |
version_a = tuple(map(int, version_a_str.split('.'))) | |
version_b = tuple(map(int, version_b_str.split('.'))) | |
# Print out user information | |
print("Local version: %s" % version_a_str) | |
print("Remote version: %s" % version_b_str) | |
# Compare and return comparison result | |
return version_a < version_b | |
def download_package(link, filename): | |
""" | |
Download the requested package. | |
:param link: Link to package. | |
:param filename: Destination filename on local filesystem. | |
""" | |
print("Start downloading package ...", end="") | |
urllib.request.urlretrieve(link, filename) | |
print(" Done") | |
def install_package(filename): | |
""" | |
Install the downloaded package with dnf. | |
:param filename: Filename of the package. | |
""" | |
print("Installing package ...", end="") | |
subprocess.run(['dnf', 'install', '-y', filename]) | |
print(" Done") | |
def clean_up(filename): | |
""" | |
Cleaning up the filesystem. | |
:param filename: Filename of the rpm package to delete. | |
""" | |
print("Cleanup filesystem ...") | |
os.remove(filename) | |
# Main entry point. | |
if __name__ == '__main__': | |
# If not root user, abort. | |
abort_if_not_root() | |
# Extract download link and get package versions (remote, local) | |
link = extract_download_link(options['page_url'], options["filter_str"]) | |
local_version = get_local_version() | |
remote_version = get_remote_version(link) | |
# Decide if a new version is found. | |
if compare_versions(local_version, remote_version): | |
print("New version found ...") | |
download_package(link, options["dest_file"]) | |
install_package(options["dest_file"]) | |
clean_up(options["dest_file"]) | |
else: | |
print("No new version found ...") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment