Added initial port of original OSX project.

- This is a copy of the [OSX](https://github.com/bkuhlmann/osx) project
  originally released on 2012-03-31. The OSX project has been
  deprecated. All future development and support will take place with
  this project instead.
- This project uses the *macOS* name in order to better match the
  updated branding and terminology used by Apple.
This commit is contained in:
Brooke Kuhlmann
2016-10-05 14:51:41 -06:00
commit 682c06f234
18 changed files with 1087 additions and 0 deletions

16
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,16 @@
## Expected Behavior
<!-- Required. Describe, in detail, the behavior experienced. -->
## Actual Behavior
<!-- Required. Describe, in detail, what should be the correct behavior. -->
## Steps to Recreate
<!-- Required. List the exact steps to the reproduce errant behavior. -->
0.
## Environment
<!-- Optional. What is your operating system, software version(s), etc. Delete if unused. -->
## Screenshots/Screencasts
<!-- Optional. Attach screenshots/screencasts that demo the behavior. Delete if unused. -->

11
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,11 @@
## Overview
<!-- Required. Why is this important/necessary? -->
## Details
<!-- Optional. List the key features/highlights as bullet points. -->
## Notes
<!-- Optional. List additional notes/references as bullet points. Delete if unused. -->
## Screenshots/Screencasts
<!-- Optional. Provide image/video support. Delete if unused. -->

3
CHANGELOG.md Normal file
View File

@@ -0,0 +1,3 @@
# v1.0.0 (2016-10-05)
- Initial version.

61
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,61 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making
participation in our project and our community a harassment-free experience for everyone, regardless of age, body size,
disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take
appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the
project or its community. Examples of representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed representative at an online or offline
event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at
[brooke@alchemists.io](mailto:brooke@alchemists.io). All complaints will be reviewed and investigated and will result in
a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain
confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be
posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent
repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

35
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,35 @@
# Overview
Thanks for taking an interest in this open source project. Your support and involvement is greatly appreciated. The
following details what you need to know in order to contribute.
# Requirements
- Follow these [Basic Programming Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/basic.md).
- Follow these [Code Review Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/code_reviews.md).
- Follow these [Git Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/git.md).
- Follow these [Bash Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/languages/bash.md).
- Follow these [CSS Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/languages/css.md).
- Follow these [Ruby Styles](https://github.com/bkuhlmann/style_guides/blob/master/programming/languages/ruby/ruby.md).
# Contributing Code
0. Read the project README thoroughly before starting.
0. Fork the master branch of the repository.
0. Ensure there are no setup, usage, and/or test issues (again, follow the README).
0. Add tests for new functionality (refactoring and documentation changes can be excluded).
0. Ensure all tests pass.
0. Push your feature branch and submit a pull request.
# Submitting Issues
0. Submit an issue via the GitHub Issues tab (assuming one does not already exist).
0. Clearly describe the issue (including steps to reproduce).
0. Specify your enviroment setup (OS, browser, language, etc. with version info).
0. Provide a stack dump (if possible).
0. Explain any additional details that might help diagnose the problem quickly.
# Feedback
Expect a response within one to three business days.
Changes, alternatives, and/or improvements might be suggested upon review.

20
LICENSE.md Normal file
View File

@@ -0,0 +1,20 @@
Copyright (c) 2016 [Alchemists](https://www.alchemists.io).
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

150
README.md Normal file
View File

@@ -0,0 +1,150 @@
# macOS
[![Patreon](https://img.shields.io/badge/patreon-donate-brightgreen.svg)](https://www.patreon.com/bkuhlmann)
Shell scripts for automated macOS machine setup. This project provides the foundational tooling for
automated macOS machine setup. To customize further see the companion
[macOS Config](https://github.com/bkuhlmann/mac_os-config) project for details.
<!-- Tocer[start]: Auto-generated, don't remove. -->
# Table of Contents
- [Features](#features)
- [Requirements](#requirements)
- [Setup](#setup)
- [Usage](#usage)
- [Customization](#customization)
- [Versioning](#versioning)
- [Code of Conduct](#code-of-conduct)
- [Contributions](#contributions)
- [License](#license)
- [History](#history)
- [Credits](#credits)
<!-- Tocer[finish]: Auto-generated, don't remove. -->
# Features
- Provides a command line interface for installation and management of macOS software.
- Downloads and installs development tooling (required by Homebrew):
- [Xcode Command Line Tools](https://developer.apple.com/xcode)
- [Java SE Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
- Downloads, installs, and configures [Homebrew](http://brew.sh) command line software.
- Downloads, installs, and configures software applications generally not in the
[App Store](http://www.apple.com/macosx/whats-new/app-store.html).
- Downloads, installs, and configures software extensions.
# Requirements
0. [macOS](https://www.apple.com/macos) (with latest software updates applied)
0. [Xcode](https://developer.apple.com/xcode) (with accepted license agreement)
# Setup
Open a terminal window and execute one of the following setup sequences depending on your version
preference:
Current Version (stable):
git clone https://github.com/bkuhlmann/mac_os.git
cd mac_os
git checkout v1.0.0
Master Version (unstable):
git clone https://github.com/bkuhlmann/mac_os.git
cd mac_os
# Usage
Run the following script:
bin/run
You will be presented with the following options:
Boot:
B: Create boot disk.
Install:
b: Apply basic system settings.
t: Install development tools.
h: Install Homebrew software.
a: Install application software.
x: Install application software extensions.
d: Apply software defaults.
s: Setup installed software.
i: Install everything (i.e. executes all install options).
Restore:
R: Restore settings from backup.
Manage:
c: Check status of managed software.
C: Caffeinate machine.
ua: Uninstall application software.
ux: Uninstall application software extension.
ra: Reinstall application software.
rx: Reinstall application software extension.
w: Clean work (temp) directory.
q: Quit/Exit.
Choose option `i` to run all install options or select a specific option to run a single option.
Each option is designed to be re-run if necessary. This can also be handy for performing upgrades,
re-running a missing/failed install, etc.
The option prompt can be skipped by passing the desired option directly to the run.sh script. For
example, executing `./run.sh i` will execute the complete software install process.
The machine should be rebooted after all install tasks have completed to ensure all settings have
been loaded.
It is recommended that the `mac_os` project directory not be deleted and kept on the local machine
in order to manage installed software and benefit from future upgrades.
## Customization
Global settings can be configured via the following script:
- `lib/settings.sh`
All script programs can be found in the `bin` folder:
- `bin/create_boot_disk` = Creates macOS boot disk.
- `bin/install_dev_tools` = Installs macOS development tools required by Homebrew.
- `bin/run` - The main script and interface for macOS setup.
The `lib` folder provides foundational functions for installing, re-installing, and uninstalling
software. Everything provided via the [macOS Config](https://github.com/bkuhlmann/mac_os-config)
project is built upon the functions found in the `lib` folder. See the
[macOS Config](https://github.com/bkuhlmann/mac_os-config) project for further details.
# Versioning
Read [Semantic Versioning](http://semver.org) for details. Briefly, it means:
- Patch (x.y.Z) - Incremented for small, backwards compatible bug fixes.
- Minor (x.Y.z) - Incremented for new, backwards compatible public API enhancements and/or bug fixes.
- Major (X.y.z) - Incremented for any backwards incompatible public API changes.
# Code of Conduct
Please note that this project is released with a [CODE OF CONDUCT](CODE_OF_CONDUCT.md). By
participating in this project you agree to abide by its terms.
# Contributions
Read [CONTRIBUTING](CONTRIBUTING.md) for details.
# License
Copyright (c) 2016 [Alchemists](https://www.alchemists.io).
Read the [LICENSE](LICENSE.md) for details.
# History
Read the [CHANGELOG](CHANGELOG.md) for details.
Built with [Bashsmith](https://github.com/bkuhlmann/bashsmith).
# Credits
Developed by [Brooke Kuhlmann](https://www.alchemists.io) at
[Alchemists](https://www.alchemists.io).

36
bin/create_boot_disk Executable file
View File

@@ -0,0 +1,36 @@
#! /bin/bash
# DESCRIPTION
# Creates macOS boot disk.
# EXECUTION
printf "macOS Boot Disk Tips\n"
printf " - Use a USB drive (8GB or higher is best).\n"
printf " - Use Disk Utility to format the USB drive (Use \"Untitled\" for the label).\n"
printf "\nmacOS Boot Disk Usage:\n"
printf " 1. Insert the USB boot disk into the machine to be upgraded.\n"
printf " 2. Reboot the machine.\n"
printf " 3. Hold down the OPTION key before the Apple logo appears.\n"
printf " 4. Select the USB boot disk from the menu.\n"
printf " 5. Format the machine's internal drive using Disk Utility.\n"
printf " 6. Install the new operating system.\n"
printf "\nmacOS Reinstall:\n"
printf " 1. Click the Apple icon from the operating system main menu.\n"
printf " 2. Select the \"Restart...\" menu option.\n"
printf " 3. Hold down the COMMAND+R keys before the Apple logo appears.\n"
printf " 4. Wait for the macOS installer to load from the recovery partition.\n"
printf " 5. Use the dialog options to launch Disk Utility, reinstall the system, etc.\n"
printf "\nCreating macOS boot disk...\n"
if [[ ! -d "$MAC_OS_INSTALLER_PATH" ]]; then
printf "ERROR: macOS installer does not exist: $MAC_OS_INSTALLER_PATH. Use the App Store to download.\n"
exit 1
fi
if [[ ! -d "$MAC_OS_BOOT_DISK_PATH" ]]; then
printf "ERROR: Boot disk must be mounted at: $MAC_OS_BOOT_DISK_PATH.\n"
exit 1
fi
sudo "$MAC_OS_BOOT_DISK_CREATOR" --volume "$MAC_OS_BOOT_DISK_PATH" --applicationpath "$MAC_OS_INSTALLER_PATH" --nointeraction

16
bin/install_dev_tools Executable file
View File

@@ -0,0 +1,16 @@
#! /bin/bash
# DESCRIPTION
# Installs development tooling requirements.
printf "Installing Xcode CLI tools...\n"
xcode-select --install
read -p "Have you completed the Xcode CLI tools install (y/n)? " response
if [[ "$response" != "y" ]]; then
printf "ERROR: Xcode CLI tools must be installed before proceeding.\n"
exit 1
fi
printf "Installing Java...\n"
install_java "$JAVA_URL" "$JAVA_VOLUME_NAME"

67
bin/run Executable file
View File

@@ -0,0 +1,67 @@
#! /bin/bash
# DESCRIPTION
# Executes the command line interface.
# USAGE
# ./run.sh OPTION
# LIBRARY
source lib/installers.sh
source lib/options.sh
source lib/reinstallers.sh
source lib/restorers.sh
source lib/settings.sh
source lib/uninstallers.sh
source lib/utilities.sh
source lib/verifiers.sh
if [[ -e "$MAC_OS_CONFIG_PATH" ]]; then
source "$MAC_OS_CONFIG_PATH/lib/settings.sh"
else
printf "ERROR: Unable to load macOS configuration: $MAC_OS_CONFIG_PATH.\n\n"
printf "Please check the following before continuing:\n"
printf " • Download the default macOS configuration here: https://github.com/bkuhlmann/mac_os-config.\n"
printf " • Customize as necessary for your setup or fork the project and make your own configuration.\n"
printf " • When finished, your folder structure should look like this:\n"
printf " • <root path>/mac_os:\n"
printf " • <root path>/mac_os-config:\n"
exit 1
fi
# EXECUTION
while true; do
if [[ $# == 0 ]]; then
printf "\nUsage: run OPTION\n"
printf "\nOSX Options:\n"
printf " Boot:\n"
printf " B: Create boot disk.\n"
printf " Install:\n"
printf " b: Apply basic settings.\n"
printf " t: Install development tools.\n"
printf " h: Install Homebrew software.\n"
printf " a: Install application software.\n"
printf " x: Install application software extensions.\n"
printf " d: Apply default settings.\n"
printf " s: Setup installed software.\n"
printf " i: Install everything (i.e. executes all install options).\n"
printf " Restore:\n"
printf " R: Restore settings from backup.\n"
printf " Manage:\n"
printf " c: Check status of managed software.\n"
printf " C: Caffeinate machine.\n"
printf " ua: Uninstall application software.\n"
printf " ux: Uninstall application software extension.\n"
printf " ra: Reinstall application software.\n"
printf " rx: Reinstall application software extension.\n"
printf " w: Clean work (temp) directory.\n"
printf " q: Quit/Exit.\n\n"
read -p "Enter selection: " response
printf "\n"
process_option $response
else
process_option $1
fi
break
done

301
lib/installers.sh Normal file
View File

@@ -0,0 +1,301 @@
#! /bin/bash
# DESCRIPTION
# Defines software installer functions.
# Mounts a disk image.
# Parameters:
# $1 = The image path.
mount_image() {
printf "Mounting image...\n"
hdiutil attach -quiet -nobrowse -noautoopen "$1"
}
export -f mount_image
# Unmounts a disk image.
# Parameters:
# $1 = The mount path.
unmount_image() {
printf "Unmounting image...\n"
hdiutil detach -force "$1"
}
export -f unmount_image
# Downloads an installer to local disk.
# Parameters:
# $1 = The URL.
# $2 = The file name.
# $3 = The HTTP header.
download_installer() {
local url="$1"
local file_name="$2"
local http_header="$3"
printf "%s\n" "Downloading $1..."
clean_work_path
mkdir $MAC_OS_WORK_PATH
curl --header "$http_header" --location --retry 3 --retry-delay 5 --fail --silent --show-error "$url" >> "$MAC_OS_WORK_PATH/$file_name"
}
export -f download_installer
# Downloads an installer to the $HOME/Downloads folder for manual use.
# Parameters:
# $1 = The URL.
# $2 = The file name.
download_only() {
if [[ -e "$HOME/Downloads/$2" ]]; then
printf "Downloaded: $2.\n"
else
printf "Downloading $1...\n"
download_installer "$1" "$2"
mv "$MAC_OS_WORK_PATH/$2" "$HOME/Downloads"
fi
}
export -f download_only
# Installs a single file.
# Parameters:
# $1 = The URL.
# $2 = The install path.
install_file() {
local file_url="$1"
local file_name=$(get_file_name "$1")
local install_path="$2"
if [[ ! -e "$install_path" ]]; then
printf "Installing: $install_path...\n"
download_installer "$file_url" "$file_name"
mkdir -p $(dirname "$install_path")
mv "$MAC_OS_WORK_PATH/$file_name" "$install_path"
printf "Installed: $file_name.\n"
verify_path "$install_path"
fi
}
export -f install_file
# Installs an application.
# Parameters:
# $1 = The application source path.
# $2 = The application name.
install_app() {
local install_root=$(get_install_root "$2")
local file_extension=$(get_file_extension "$2")
printf "Installing: $install_root/$2...\n"
case $file_extension in
'app')
cp -a "$1/$2" "$install_root";;
'prefPane')
sudo cp -pR "$1/$2" "$install_root";;
'qlgenerator')
sudo cp -pR "$1/$2" "$install_root" && qlmanage -r;;
*)
printf "ERROR: Unknown file extension: $file_extension.\n"
esac
}
export -f install_app
# Installs a package.
# Parameters:
# $1 = The package source path.
# $2 = The application name.
install_pkg() {
local install_root=$(get_install_root "$2")
printf "Installing: $install_root/$2...\n"
local package=$(sudo find "$1" -maxdepth 1 -type f -name "*.pkg" -o -name "*.mpkg")
sudo installer -pkg "$package" -target /
}
export -f install_pkg
# Installs Java.
# Parameters:
# $1 = The URL.
# $2 = The volume name.
install_java() {
local url="$1"
local volume_path="/Volumes/$2"
local app_name="java"
local install_path="/usr/bin/$app_name"
local download_file="download.dmg"
download_installer "$url" "$download_file" "Cookie: oraclelicense=accept-securebackup-cookie"
mount_image "$MAC_OS_WORK_PATH/$download_file"
local package=$(sudo find "$volume_path" -maxdepth 1 -type f -name "*.pkg")
sudo installer -pkg "$package" -target /
unmount_image "$volume_path"
printf "Installed: $app_name.\n"
}
export -f install_java
# Installs an application via a DMG file.
# Parameters:
# $1 = The URL.
# $2 = The mount path.
# $3 = The application name.
install_dmg_app() {
local url="$1"
local mount_point="/Volumes/$2"
local app_name="$3"
local install_path=$(get_install_path "$app_name")
local download_file="download.dmg"
if [[ ! -e "$install_path" ]]; then
download_installer "$url" "$download_file"
mount_image "$MAC_OS_WORK_PATH/$download_file"
install_app "$mount_point" "$app_name"
unmount_image "$mount_point"
verify_application "$app_name"
fi
}
export -f install_dmg_app
# Installs a package via a DMG file.
# Parameters:
# $1 = The URL.
# $2 = The mount path.
# $3 = The application name.
install_dmg_pkg() {
local url="$1"
local mount_point="/Volumes/$2"
local app_name="$3"
local install_path=$(get_install_path "$app_name")
local download_file="download.dmg"
if [[ ! -e "$install_path" ]]; then
download_installer "$url" "$download_file"
mount_image "$MAC_OS_WORK_PATH/$download_file"
install_pkg "$mount_point" "$app_name"
unmount_image "$mount_point"
printf "Installed: $app_name.\n"
verify_application "$app_name"
fi
}
export -f install_dmg_pkg
# Installs an application via a zip file.
# Parameters:
# $1 = The URL.
# $2 = The application name.
install_zip_app() {
local url="$1"
local app_name="$2"
local install_path=$(get_install_path "$app_name")
local download_file="download.zip"
if [[ ! -e "$install_path" ]]; then
download_installer "$url" "$download_file"
(
printf "Preparing...\n"
cd "$MAC_OS_WORK_PATH"
unzip -q "$download_file"
)
install_app "$MAC_OS_WORK_PATH" "$app_name"
printf "Installed: $app_name.\n"
verify_application "$app_name"
fi
}
export -f install_zip_app
# Installs an application via a tar file.
# Parameters:
# $1 = The URL.
# $2 = The application name.
# $3 = The decompress options.
install_tar_app() {
local url="$1"
local app_name="$2"
local options="$3"
local install_path=$(get_install_path "$app_name")
local download_file="download.tar"
if [[ ! -e "$install_path" ]]; then
download_installer "$url" "$download_file"
(
printf "Preparing...\n"
cd "$MAC_OS_WORK_PATH"
tar "$options" "$download_file"
)
install_app "$MAC_OS_WORK_PATH" "$app_name"
printf "Installed: $app_name.\n"
verify_application "$app_name"
fi
}
export -f install_tar_app
# Installs a package via a zip file.
# Parameters:
# $1 = The URL.
# $2 = The application name.
install_zip_pkg() {
local url="$1"
local app_name="$2"
local install_path=$(get_install_path "$app_name")
local download_file="download.zip"
if [[ ! -e "$install_path" ]]; then
download_installer "$url" "$download_file"
(
printf "Preparing...\n"
cd "$MAC_OS_WORK_PATH"
unzip -q "$download_file"
)
install_pkg "$MAC_OS_WORK_PATH" "$app_name"
printf "Installed: $app_name.\n"
verify_application "$app_name"
fi
}
export -f install_zip_pkg
# Installs application code from a Git repository.
# Parameters:
# $1 = Repository URL.
# $2 = Install path.
# $3 = Git clone options (if any).
install_git_app() {
local repository_url="$1"
local app_name=$(get_file_name "$2")
local install_path="$2"
local options="--quiet"
if [[ -n "$3" ]]; then
local options="$options $3"
fi
if [[ ! -e "$install_path" ]]; then
printf "Installing: $install_path/$app_name...\n"
git clone $options "$repository_url" "$install_path"
printf "Installed: $app_name.\n"
verify_path "$install_path"
fi
}
export -f install_git_app
# Installs settings from a Git repository.
# Parameters:
# $1 = The repository URL.
# $2 = The repository version.
# $3 = The project directory.
# $4 = The script to run (including any arguments).
install_git_project() {
local repo_url="$1"
local repo_version="$2"
local project_dir="$3"
local script="$4"
git clone "$repo_url"
(
cd "$project_dir"
git checkout "$repo_version"
eval "$script"
)
rm -rf "$project_dir"
}
export -f install_git_project

60
lib/options.sh Normal file
View File

@@ -0,0 +1,60 @@
#! /bin/bash
# DESCRIPTION
# Defines command line prompt options.
# Process option selection.
# Parameters:
# $1 = The option to process.
process_option() {
case $1 in
'B')
bin/create_boot_disk;;
'b')
"$MAC_OS_CONFIG_PATH/bin/apply_basic_settings";;
't')
bin/install_dev_tools;;
'h')
"$MAC_OS_CONFIG_PATH/bin/install_homebrew";;
'a')
"$MAC_OS_CONFIG_PATH/bin/install_applications";;
'x')
"$MAC_OS_CONFIG_PATH/bin/install_extensions";;
'd')
"$MAC_OS_CONFIG_PATH/bin/apply_default_settings";;
's')
"$MAC_OS_CONFIG_PATH/bin/setup_software";;
'i')
caffeinate_machine
"$MAC_OS_CONFIG_PATH/bin/apply_basic_settings"
bin/install_dev_tools
"$MAC_OS_CONFIG_PATH/bin/install_homebrew"
"$MAC_OS_CONFIG_PATH/bin/install_applications"
"$MAC_OS_CONFIG_PATH/bin/install_extensions"
"$MAC_OS_CONFIG_PATH/bin/apply_default_settings"
"$MAC_OS_CONFIG_PATH/bin/setup_software"
clean_work_path;;
'R')
"$MAC_OS_CONFIG_PATH/bin/restore_backup";;
'c')
verify_homebrews
verify_applications
verify_extensions;;
'C')
caffeinate_machine;;
'ua')
uninstall_application;;
'ux')
uninstall_extension;;
'ra')
reinstall_application;;
'rx')
reinstall_extension;;
'w')
clean_work_path;;
'q');;
*)
printf "ERROR: Invalid option.\n";;
esac
}
export -f process_option

18
lib/reinstallers.sh Normal file
View File

@@ -0,0 +1,18 @@
#! /bin/bash
# DESCRIPTION
# Defines reinstall functions.
# Reinstall application.
reinstall_application() {
uninstall_application
scripts/applications.sh
}
export -f reinstall_application
# Reinstall extension.
reinstall_extension() {
uninstall_extension
scripts/extensions.sh
}
export -f reinstall_extension

31
lib/restorers.sh Normal file
View File

@@ -0,0 +1,31 @@
#! /bin/bash
# DESCRIPTION
# Defines software restore functions.
# Label: Restore Preference
# Description: Restores an application preference.
# Parameters: $1 (required) - The backup volume root path, $2 (required) - The preference file.
restore_preference() {
local backup_root="$1"
local preference_file="$2"
local backup_path="$backup_root/Users/$USER/Library/Preferences/$preference_file"
local restore_root="$HOME/Library/Preferences"
cp -p "$backup_path" "$restore_root"
}
export -f restore_preference
# Label: Restore Application Support
# Description: Restores application support files.
# Parameters: $1 (required) - The backup volume root path, $2 required - The application name.
restore_app_support() {
local backup_root="$1"
local app_name="$2"
local backup_path="$backup_root/Users/$USER/Library/Application Support/$app_name"
local restore_path="$HOME/Library/Application Support"
mkdir -p "$restore_path"
cp -pR "$backup_path" "$restore_path"
}
export -f restore_app_support

22
lib/settings.sh Normal file
View File

@@ -0,0 +1,22 @@
#! /bin/bash
# DESCRIPTION
# Defines global settings.
# SETTINGS
# General
set -o nounset
set -o errexit
set -o pipefail
IFS=$'\n\t'
# Globals
export MAC_OS_BOOT_DISK_CREATOR="/Applications/Install macOS Sierra.app/Contents/Resources/createinstallmedia"
export MAC_OS_BOOT_DISK_PATH="/Volumes/Untitled"
export MAC_OS_INSTALLER_PATH="/Applications/Install macOS Sierra.app"
export MAC_OS_WORK_PATH=/tmp/downloads
export MAC_OS_CONFIG_PATH="../mac_os-config"
# Java
export JAVA_VOLUME_NAME="JDK 8 Update 101"
export JAVA_URL="http://download.oracle.com/otn-pub/java/jdk/8u101-b13/jdk-8u101-macosx-x64.dmg"

53
lib/uninstallers.sh Normal file
View File

@@ -0,0 +1,53 @@
#! /bin/bash
# DESCRIPTION
# Defines uninstall functions.
# Uninstalls selected application.
uninstall_application() {
# Only use environment keys that end with "APP_NAME".
local keys=($(set | awk -F "=" '{print $1}' | grep ".*APP_NAME"))
printf "Select application to uninstall:\n"
for ((index = 0; index < ${#keys[*]}; index++)); do
local app_file="${!keys[$index]}"
printf " $index: ${app_file}\n"
done
printf " q: Quit/Exit\n\n"
read -p "Enter selection: " response
printf "\n"
local regex="^[0-9]+$"
if [[ $response =~ $regex ]]; then
local app_file="${!keys[$response]}"
local app_path=$(get_install_path "${app_file}")
sudo rm -rf "$app_path"
printf "Uninstalled: ${app_path}\n"
fi
}
export -f uninstall_application
# Uninstalls selected extension.
uninstall_extension() {
# Only use environment keys that end with "EXTENSION_PATH".
local keys=($(set | awk -F "=" '{print $1}' | grep ".*EXTENSION_PATH"))
printf "Select extension to uninstall:\n"
for ((index = 0; index < ${#keys[*]}; index++)); do
local extension_path="${!keys[$index]}"
printf " $index: ${extension_path}\n"
done
printf " q: Quit/Exit\n\n"
read -p "Enter selection: " response
printf "\n"
local regex="^[0-9]+$"
if [[ $response =~ $regex ]]; then
local extension_path="${!keys[$response]}"
rm -rf "${extension_path}"
printf "Uninstalled: ${extension_path}\n"
fi
}
export -f uninstall_extension

79
lib/utilities.sh Normal file
View File

@@ -0,0 +1,79 @@
#! /bin/bash
# DESCRIPTION
# Defines general utility functions.
# Answers the file name.
# Parameters:
# $1 = The file path.
get_file_name() {
printf "${1##*/}" # Answers file or directory name.
}
export -f get_file_name
# Answers the file extension.
# Parameters:
# $1 = The file name.
get_file_extension() {
local name=$(get_file_name "$1")
local extension="${1##*.}" # Excludes dot.
if [[ "$name" == "$extension" ]]; then
printf ''
else
printf "$extension"
fi
}
export -f get_file_extension
# Answers the root install path for file name.
# Parameters:
# $1 = The file name.
get_install_root() {
local file_name="$1"
local file_extension=$(get_file_extension "$file_name")
# Dynamically build the install path based on file extension.
case $file_extension in
'')
printf "/usr/local/bin";;
'app')
printf "/Applications";;
'prefPane')
printf "/Library/PreferencePanes";;
'qlgenerator')
printf "/Library/QuickLook";;
*)
printf "/tmp/unknown";;
esac
}
export -f get_install_root
# Answers the full install path (including file name) for file name.
# Parameters:
# $1 = The file name.
get_install_path() {
local file_name="$1"
local install_path=$(get_install_root "$file_name")
printf "$install_path/$file_name"
}
export -f get_install_path
# Cleans work path for temporary processing of installs.
clean_work_path() {
rm -rf "$MAC_OS_WORK_PATH"
}
export -f clean_work_path
# Caffeinate machine.
caffeinate_machine() {
local pid=$(ps aux | grep caffeinate | grep -v grep | awk '{print $2}')
if [[ -n "$pid" ]]; then
printf "Whoa, tweaker, machine is already caffeinated!\n"
else
caffeinate -s -u -d -i -t 3153600000 > /dev/null &
printf "Machine caffeinated.\n"
fi
}
export -f caffeinate_machine

108
lib/verifiers.sh Normal file
View File

@@ -0,0 +1,108 @@
#! /bin/bash
# DESCRIPTION
# Defines verification/validation functions.
# Verifies Homebrew software exists.
# Parameters:
# $1 = The file name.
verify_homebrew() {
local application="$1"
local applications="$2"
if [[ "${applications[*]}" != *"$application"* ]]; then
printf " - Missing: $application\n"
fi
}
export -f verify_homebrew
# Checks for missing Homebrew software.
verify_homebrews() {
printf "Checking Homebrew software...\n"
local applications="$(brew list)"
while read line; do
# Skip blank or comment lines.
if [[ "$line" == "brew install"* ]]; then
local application=$(printf "$line" | awk '{print $3}')
# Exception: "gpg" is the binary but is listed as "gnugp".
if [[ "$application" == "gpg" ]]; then
application="gnupg"
fi
# Exception: "hg" is the binary but is listed as "mercurial".
if [[ "$application" == "hg" ]]; then
application="mercurial"
fi
verify_homebrew "$application" "${applications[*]}"
fi
done < "$PWD/scripts/homebrew.sh"
printf "Homebrew check complete.\n"
}
export -f verify_homebrews
# Verifies application exists.
# Parameters:
# $1 = The file name.
verify_application() {
local file_name="$1"
# Display the missing install if not found.
local install_path=$(get_install_path "$file_name")
if [[ ! -e "$install_path" ]]; then
printf " - Missing: $file_name\n"
fi
}
export -f verify_application
# Checks for missing applications suffixed by "APP_NAME" as defined in settings.sh.
verify_applications() {
printf "\nChecking application software...\n"
# Only use environment keys that end with "APP_NAME".
local file_names=$(set | awk -F "=" '{print $1}' | grep ".*APP_NAME")
# For each application name, check to see if the application is installed. Otherwise, skip.
for name in $file_names; do
# Pass the key value to verfication.
verify_application "${!name}"
done
printf "Application software check complete.\n"
}
export -f verify_applications
# Verifies path exists.
# Parameters:
# $1 = The path.
verify_path() {
local path="$1"
# Display the missing path if not found.
if [[ ! -e "$path" ]]; then
printf " - Missing: $path\n"
fi
}
export -f verify_path
# Checks for missing extensions suffixed by "EXTENSION_PATH" as defined in settings.sh.
verify_extensions() {
printf "\nChecking application extensions...\n"
# Only use environment keys that end with "EXTENSION_PATH".
local extensions=$(set | awk -F "=" '{print $1}' | grep ".*EXTENSION_PATH")
# For each extension, check to see if the extension is installed. Otherwise, skip.
for extension in $extensions; do
# Evaluate/extract the key (extension) value and pass it on for verfication.
verify_path "${!extension}"
done
printf "Application extension check complete.\n"
}
export -f verify_extensions