#!/bin/bash
# sys/tool/git - git support

set -e


######
# Native Dependencies

sys_tool_git_client_packages=( git )


######
# Library Configuration

sys_tool_git_config_init() {
	# $git_repodir - Location of shared repositories
	lib_setting_vars git_repodir
	git_repodir=/var/cache/git

	# $git_short - Set to true to pass ``--short``
	lib_setting_vars git_short
	git_short=false

	# $git_porcelin - Set to true to pass ``--porcelin``
	lib_setting_vars git_porcelin
	git_porcelin=false

	# $git_push_tags - Set to true to pass ``--tags`` to ``git push``
	lib_setting_vars git_push_tags
	git_push_tags=false
}


######
# Internal Functions

# git_run() - Runs the ``git`` program.
git_run() {
	local -a opts
	$git_porcelin && opts+=( --porcelin )
	opts+=( "$@" )
	run git "$@"
}


######
# Repository Management

# git_create() - Creates an empty repository in a new directory ($2).
git_create() {
	local dir=$1
	[ ! -d "$dir" ] || error "$dir: repository directory exists"
	run_mkdir "$dir"
	git_init "$dir"
}

# git_init() - Initializes a repository in the given directory ($2),
git_init() {
	local dir=$1
	run_in_dir "$dir" git_run init
}

# git_clone() - Clones a repository ($1) into a new directory ($2).
git_clone() {
	has_args 2 "$@"
	local url=$1
	local dir=$2
	git_run clone "$url" "$dir"
}


# git_pull() - Runs ``git pull`` with the given arguments ($@).
git_pull() { git_run pull "$@"; }

# git_update() - Updates a repository by rebasing local current changes
# onto the remote branch.  This will fail if there are unstashed changes
# or if a merge conflict occurrs.
# $1 - Path to repository (optional)
git_update() { git_pull --rebase; }

# git_fetch() - Retrieves new objects for a repository.
git_fetch() { git_run fetch "$@"; }

# git_clone_or_update() - Clones or updates a repository ($1) at the
# given path ($2).
git_clone_or_update() {
	local url=$1
	local dir=$2
	if [ -d "$dir" ]; then
		run_in_dir "$dir" git_update
	else
		git_clone "$url" "$dir"
	fi
}

# git_push() - Runs ``git push`` to send changes to the remote.
# If ``$git_push_tags`` is `true`, this will push tags.
# $@ - Extra arguments (optional)
git_push() {
	local -a opts=()
	! $git_push_tags || opts+=( --tags )
	git_run push "${opts[@]}" "$@"
}

# git_push_all() - Runs ``git push`` to send changes to the remote.
git_push_all() {
	git_push "$@"
	git_push_tags=true git_push "$@"
}


######
# Working Copies

# git_repo_dir() - Prints the path to the current working copy.
# The resulting path will contain the ``.git`` directory for the
# current repository.
git_repo_dir() {
	local path=$PWD
	while true; do
		if [ -d "$path/.git" ]; then
			debug "found git repo: $path"
			echo "$path"
			return 0
		fi
		if [ "$path" = "" ]; then
			error "git repo not found in path"
			break
		fi
		path=${path%/*}
	done
}

# git_checkout() - Runs ``git checkout`` with the given arguments ($@).
git_checkout() { git_run checkout "$@"; }

# git_status() - Runs ``git status`` with the given arguments ($@).
git_status() { git_run status "$@"; }

# git_status_new() - Prints all untracked changes to repository files
# and lists top-level untracked files.  This does not print contents of
# untracked directories; for that, use ``git_status_all()``.
git_status_new() { git_status --untracked-files normal "$@"; }

# git_status_repo() - Prints all untracked changes to repository files
git_status_repo() { git_status --untracked-files no "$@"; }

# git_status_all() - Prints all untracked changes and files
git_status_all() { git_status --untracked-files all "$@"; }


######
# Staging

# git_add() - Adds files ($@) to git index.
# $@ - Files to add
git_add() { git_run add "$@"; }

# git_mv() - Moves tracked files ($@).
# $@ - Arguments
git_mv() {
	file_mkdir "$dst"
	git_run mv "$@"
}

# git_reset() - Runs ``git reset``
# $@ - Arguments
git_reset() { git_run reset "$@"; }

# git_reset_soft() - Performas a soft reset, removing files from the index.
# A soft reset will leave the changes intact in the working copy.
# $@ - Arguments
git_reset_soft() { git_reset --soft "$@"; }

# git_reset_hard() - Performas a hard reset.  In addition to the actions of
# a soft reset, a hard reset reverts the changes in the working copy.
# $@ - Arguments
git_reset_hard() { git_reset --hard "$@"; }


######
# Commits

# git_commit() - Runs ``git commit``
# $@ - Extra arguments (optional)
git_commit() {  git_run commit "$@"; }

git_commit_fast() {
	local git_porcelin=true
	git_status
}

# git_commit_drop() - Drops the commit at the tip of the current branch.
git_commit_drop() { git_reset_hard HEAD^; }


######
# Branches

# git_rev_parse() - Runs the ``rev-parse`` command
git_rev_parse() {
	git_run rev-parse "$@"
}


######
# Tags

# git_tag() - Creates a new tag.
# $@ - Tag names
git_tag() { git_run tag "$@"; }

# git_tag_delete() - Delete the name tag.
# $@ - Tag names
git_tag_delete() { git_run tag -d "$@"; }

# git_tag_prev() - Prints the name of the last tag on the current branch.
git_tag_prev() { git_run describe --tags --abbrev=0 "${1:-HEAD}^1"; }


######
# Logs

# git_log() - Views the git log
# $@ - Extra arguments (optional)
git_log() {
	git_run log "$@"
}

# git_commit_title() - Prints title of the commit message from the
# given revision ($1).
# $1 - Revision
git_commit_title() {
	local rev=$1
	git_log --oneline $rev^..$rev | cut -f2- -d' '
}

View the Developer Guide Index

View the Reference Manual Index


Generated on Fri Jul 28 14:36:09 PDT 2017 by mcsh d14 v0.23.0.