#!/usr/bin/env python """ Installs my favorite programs on a new Fedora system. Most things are generally safe enough to install on any Fedora system, but there are command line flags for some of the possibly dangerous options: --xfce This installs MATE components on an Xfce desktop. Normally the Xfce desktop would be automatically detected, but if not, provide this option. --plymouth, -p Install and configure my favorite Plymouth theme (solar). This option must be explicitly passed in because changing the Plymouth theme might not always be desired. --wl Install the Broadcom wireless drivers (akmod-wl). Only do this on systems that need the `wl` driver. --dry-run Do not actually change any packages on the system. Fonts: - Microsoft core fonts - Emoji fonts Apps: - Firefox, Thunderbird - The GIMP - Banshee - MATE Desktop counterparts to my favorite old GNOME apps (--xfce only): - Eye of MATE (Image viewer, fork of Eye of GNOME) - Engrampa (archive manager, fork of file-roller) - Pluma (text editor, fork of gedit) - Atril (PDF viewer, fork of evince) Dev stuff: - zsh - python-virtualenvwrapper - git - golang - pyflakes - nodejs, npm Filesystems: - fuse-encfs - fuse-exfat - gvfs-mtp Misc: - Video codecs - h264 support for Firefox HTML5 videos - VLC Media Player Themes: - Bluecurve Cursor Theme - Solar Plymouth Theme --Kirsle http://sh.kirsle.net/ """ import argparse import hashlib import os import subprocess class Application(object): def __init__(self, args): self.to_install = [] # Detect desktop environments. desktop = os.environ.get("XDG_CURRENT_DESKTOP", "").upper() self.xfce = args.xfce or desktop == "XFCE" # More args. self.noop = args.dry_run self.plymouth = args.plymouth self.wl = args.wl # Using custom configs? self.custom = self.xfce or self.plymouth or self.wl def main(self): """Main entry point of the app.""" # Update first. self.shell("sudo dnf -y update") # The latest RPM Fusion. if not self.test("rpm -q rpmfusion-free-release"): self.shell("sudo dnf install --nogpgcheck http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm") # Microsoft core fonts and Emoji support. if not self.test("rpm -q msttcore-fonts"): # The fonts aren't signed, so verify their checksum. self.shell("wget -O /tmp/msttcore-fonts.rpm https://rpm.kirsle.net/any/rpm/msttcore-fonts-2.0-3.noarch.rpm") expect_sum = "a20ecca993827d10bb51118a0cfdf8a1e65f161a78361bee865a138ca5a4f43f" if not self.noop and self.sha256sum("/tmp/msttcore-fonts.rpm") != expect_sum: print("!!! WARNING !!!") print("The SHA256 hash of msttcore-fonts doesn't match what I expected!") print("Expected: {}".format(expect_sum)) print(" Got: {}".format(self.sha256sum("/tmp/msttcore-fonts.rpm"))) input("Press any key to continue. . .") else: self.shell("sudo dnf install /tmp/msttcore-fonts.rpm") if os.path.isfile("/tmp/msttcore-fonts.rpm"): os.unlink("/tmp/msttcore-fonts.rpm") self.install("gdouros-symbola-fonts") # Themes self.install("bluecurve-cursor-theme") if self.plymouth and not self.test("rpm -q plymouth-theme-solar"): self.install("plymouth-theme-solar") self.commit() self.shell("sudo plymouth-set-default-theme solar && sudo dracut -f") # My favorite desktop apps. self.install( "firefox", "thunderbird", "gimp", "libreoffice", ) # Ones that I mainly want on the Xfce desktop (MATE apps) if self.xfce: self.install( "pluma", # gedit (Text Editor) "atril", # evince (Document Viewer) "engrampa", # file-roller (Archive Manager) "eom", # eog (Picture Viewer) "tumbler", # thumbnailer for Thunar file browser "ffmpegthumbnailer", # video thumbnail support ) # Development stuff. self.install( "ctags", "git", "golang", "nodejs", "npm", "zsh", ) # Filesystems self.install("fuse-encfs", "fuse-exfat", "gvfs-mtp") # Codecs and plugins and Firefox h264 video support self.install("gstreamer1-libav", "gstreamer1-vaapi", "gstreamer1-plugins-good", "gstreamer1-plugins-ugly", "gstreamer1-plugins-good-extras", "gstreamer1-plugins-bad-free", "gstreamer1-plugins-bad-freeworld", "vlc") self.commit() print("\nSuccess! Everything has been set up and configured.") if self.custom: print("\nThe following custom software groups were included:\n") if self.xfce: print("\tThe XFCE set (MATE desktop utilities for XFCE)") if self.plymouth: print("\tThe Solar Plymouth theme") if self.wl: print("\tThe Broadcom proprietary WiFi driver") def install(self, *rpm): """Name an rpm I wanna install. Checks if it's already installed first, then adds it to the self.to_install list.""" for item in rpm: if not self.test("rpm -q {}".format(item)): print("* To install: {}".format(item)) self.to_install.append(item) def commit(self): """Install the pending RPMs.""" if len(self.to_install) > 0: print("Installing...") self.shell("sudo dnf -y install {}".format(" ".join(self.to_install))) self.to_install = [] def shell(self, cmd): print("EXECUTE: {}".format(cmd)) if self.noop: return subprocess.call(cmd, shell=True) def test(self, command): """Test if a command exits successfully.""" if self.noop: return False try: subprocess.check_call("{} >/dev/null 2>&1".format(command), shell=True) return True except subprocess.CalledProcessError: return False def sha256sum(self, file): """Get the SHA256 checksum of a file.""" m = hashlib.sha256() with open(file, 'rb') as fh: m.update(fh.read()) return m.hexdigest() if __name__ == "__main__": parser = argparse.ArgumentParser(description="Noah's Fedora Setup Script") parser.add_argument("--xfce", "-x", help="Assume the Xfce desktop environment and install useful MATE " "utilities (pluma, atril, eom, engrampa)", action="store_true", ) parser.add_argument("--plymouth", "-p", help="Install and configure the Solar plymouth theme (only if the " "theme is not presently installed)", action="store_true", ) parser.add_argument("--wl", help="Install the Broadcom `wl` WiFi driver (akmod-wl)", action="store_true", ) parser.add_argument("--dry-run", help="Do not actually modify any packages on the system.", action="store_true", ) app = Application(args=parser.parse_args()) app.main()