Copy config removing sensitive data
This commit is contained in:
parent
d15767a938
commit
490e0c86c5
89 changed files with 12214 additions and 0 deletions
26
bin/addhost
Executable file
26
bin/addhost
Executable file
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/bash
|
||||
if [ $1 ]; then
|
||||
case $1 in
|
||||
-h|--help)
|
||||
echo "Add entrys to your hosts file"
|
||||
echo ""
|
||||
echo -e "addhost domain.com\t\t\t\tadds domain.com to your hosts and points to local machine"
|
||||
echo -e "addhost (alex|aaron|jonathan) domain.com\tadds domain.com to your hosts and points to persons machine"
|
||||
;;
|
||||
alex)
|
||||
echo -e "10.0.1.201\t$2" | sudo tee -a /etc/hosts
|
||||
;;
|
||||
aaron)
|
||||
echo -e "10.0.1.202\t$2" | sudo tee -a /etc/hosts
|
||||
;;
|
||||
jonathan)
|
||||
echo -e "10.0.1.203\t$2" | sudo tee -a /etc/hosts
|
||||
;;
|
||||
*)
|
||||
echo -e "127.0.0.1\t$1" | sudo tee -a /etc/hosts
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo "You need to add at least a domain"
|
||||
fi
|
||||
|
3
bin/capslock
Executable file
3
bin/capslock
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/bash
|
||||
v=$(xset -q | grep Caps)
|
||||
echo ${v:7:17}
|
22
bin/code-to-pdf
Executable file
22
bin/code-to-pdf
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
TITLE="$1"
|
||||
shift
|
||||
|
||||
enscript -1 --media=A4 \
|
||||
--toc \
|
||||
--header '%H - $N | | page $% of $= in file $v' \
|
||||
--font "Menlo-Regular@8.5" \
|
||||
--header-font "Menlo-Bold@10" \
|
||||
--margins=60:60:18:60 \
|
||||
--fancy-header=sjl \
|
||||
--title $TITLE \
|
||||
--baselineskip 3 \
|
||||
--line-numbers \
|
||||
--highlight \
|
||||
--color \
|
||||
--mark-wrapped-lines=arrow \
|
||||
-p - \
|
||||
--word-wrap $* \
|
||||
| ps2pdf -i -o code.pdf
|
||||
|
157
bin/csvtomd
Executable file
157
bin/csvtomd
Executable file
|
@ -0,0 +1,157 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
csvtomd 0.2.1
|
||||
|
||||
Convert your CSV files into Markdown tables.
|
||||
|
||||
More info: http://github.com/mplewis/csvtomd
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import sys
|
||||
|
||||
|
||||
def check_negative(value):
|
||||
try:
|
||||
ivalue = int(value)
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError(
|
||||
'"%s" must be an integer' % value)
|
||||
if ivalue < 0:
|
||||
raise argparse.ArgumentTypeError(
|
||||
'"%s" must not be a negative value' % value)
|
||||
return ivalue
|
||||
|
||||
|
||||
def pad_to(unpadded, target_len):
|
||||
"""
|
||||
Pad a string to the target length in characters, or return the original
|
||||
string if it's longer than the target length.
|
||||
"""
|
||||
under = target_len - len(unpadded)
|
||||
if under <= 0:
|
||||
return unpadded
|
||||
return unpadded + (' ' * under)
|
||||
|
||||
|
||||
def normalize_cols(table):
|
||||
"""
|
||||
Pad short rows to the length of the longest row to help render "jagged"
|
||||
CSV files
|
||||
"""
|
||||
longest_row_len = max([len(row) for row in table])
|
||||
for row in table:
|
||||
while len(row) < longest_row_len:
|
||||
row.append('')
|
||||
return table
|
||||
|
||||
|
||||
def pad_cells(table):
|
||||
"""Pad each cell to the size of the largest cell in its column."""
|
||||
col_sizes = [max(map(len, col)) for col in zip(*table)]
|
||||
for row in table:
|
||||
for cell_num, cell in enumerate(row):
|
||||
row[cell_num] = pad_to(cell, col_sizes[cell_num])
|
||||
return table
|
||||
|
||||
|
||||
def horiz_div(col_widths, horiz, vert, padding):
|
||||
"""
|
||||
Create the column dividers for a table with given column widths.
|
||||
|
||||
col_widths: list of column widths
|
||||
horiz: the character to use for a horizontal divider
|
||||
vert: the character to use for a vertical divider
|
||||
padding: amount of padding to add to each side of a column
|
||||
"""
|
||||
horizs = [horiz * w for w in col_widths]
|
||||
div = ''.join([padding * horiz, vert, padding * horiz])
|
||||
return div.join(horizs)
|
||||
|
||||
|
||||
def add_dividers(row, divider, padding):
|
||||
"""Add dividers and padding to a row of cells and return a string."""
|
||||
div = ''.join([padding * ' ', divider, padding * ' '])
|
||||
return div.join(row)
|
||||
|
||||
|
||||
def md_table(table, *, padding=1, divider='|', header_div='-'):
|
||||
"""
|
||||
Convert a 2D array of items into a Markdown table.
|
||||
|
||||
padding: the number of padding spaces on either side of each divider
|
||||
divider: the vertical divider to place between columns
|
||||
header_div: the horizontal divider to place between the header row and
|
||||
body cells
|
||||
"""
|
||||
table = normalize_cols(table)
|
||||
table = pad_cells(table)
|
||||
header = table[0]
|
||||
body = table[1:]
|
||||
|
||||
col_widths = [len(cell) for cell in header]
|
||||
horiz = horiz_div(col_widths, header_div, divider, padding)
|
||||
|
||||
header = add_dividers(header, divider, padding)
|
||||
body = [add_dividers(row, divider, padding) for row in body]
|
||||
|
||||
table = [header, horiz]
|
||||
table.extend(body)
|
||||
table = [row.rstrip() for row in table]
|
||||
return '\n'.join(table)
|
||||
|
||||
|
||||
def csv_to_table(file, delimiter):
|
||||
return list(csv.reader(file, delimiter=delimiter))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Read one or more CSV files and output their contents in '
|
||||
'the form of Markdown tables.')
|
||||
parser.add_argument('files', metavar='csv_file', type=str, nargs='*',
|
||||
default=['-'],
|
||||
help="One or more CSV files to be converted. "
|
||||
"Use - for stdin.")
|
||||
parser.add_argument('-n', '--no-filenames', action='store_false',
|
||||
dest='show_filenames',
|
||||
help="Don't display filenames when outputting "
|
||||
"multiple Markdown tables.")
|
||||
parser.add_argument('-p', '--padding', type=check_negative, default=2,
|
||||
help="The number of spaces to add between table cells "
|
||||
"and column dividers. Default is 2 spaces.")
|
||||
parser.add_argument('-d', '--delimiter', default=',',
|
||||
help='The delimiter to use when parsing CSV data. '
|
||||
'Default is "%(default)s"')
|
||||
|
||||
args = parser.parse_args()
|
||||
first = True
|
||||
|
||||
if '-' in args.files and len(args.files) > 1:
|
||||
print('Standard input can only be used alone.', file=sys.stderr)
|
||||
exit(1)
|
||||
for file_num, filename in enumerate(args.files):
|
||||
# Print space between consecutive tables
|
||||
if not first:
|
||||
print('')
|
||||
else:
|
||||
first = False
|
||||
# Read the CSV files
|
||||
if filename == '-':
|
||||
table = csv_to_table(sys.stdin, args.delimiter)
|
||||
else:
|
||||
with open(filename, 'rU') as f:
|
||||
table = csv_to_table(f, args.delimiter)
|
||||
# Print filename for each table if --no-filenames wasn't passed and
|
||||
# more than one CSV was provided
|
||||
file_count = len(args.files)
|
||||
if args.show_filenames and file_count > 1:
|
||||
print(filename + '\n')
|
||||
# Generate and print Markdown table
|
||||
print(md_table(table, padding=args.padding))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
80
bin/extract
Executable file
80
bin/extract
Executable file
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
if [ -f $1 ] ; then
|
||||
case $1 in
|
||||
*.tar.bz2)
|
||||
if [ "$2" ]; then
|
||||
tar xvjf $1 -C $2
|
||||
else
|
||||
tar xvjf $1
|
||||
fi
|
||||
;;
|
||||
*.tar.gz)
|
||||
if [ "$2" ]; then
|
||||
tar xvzf $1 -C $2
|
||||
else
|
||||
tar xvzf $1
|
||||
fi
|
||||
;;
|
||||
*.bz2)
|
||||
if [ "$2" ]; then
|
||||
bunzip -c $1 > $2
|
||||
else
|
||||
bunzip $1
|
||||
fi
|
||||
;;
|
||||
#*.rar) rar x $1 ;;
|
||||
*.gz)
|
||||
if [ "$2" ]; then
|
||||
gunzip -c $1 > $2
|
||||
else
|
||||
gunzip $1
|
||||
fi
|
||||
;;
|
||||
*.tar)
|
||||
if [ "$2" ]; then
|
||||
tar xvf $1 -C $2
|
||||
else
|
||||
tar xvf $1
|
||||
fi
|
||||
;;
|
||||
*.tbz2)
|
||||
if [ "$2" ]; then
|
||||
tar xvjf $1 -C $2
|
||||
else
|
||||
tar xvjf $1
|
||||
fi
|
||||
;;
|
||||
*.tgz)
|
||||
if [ "$2" ]; then
|
||||
tar xvzf $1 -C $2
|
||||
else
|
||||
tar xvzf $1
|
||||
fi
|
||||
;;
|
||||
*.zip)
|
||||
if [ "$2" ]; then
|
||||
unzip $1 -d $2
|
||||
else
|
||||
unzip $1
|
||||
fi
|
||||
;;
|
||||
*.Z)
|
||||
if [ "$2" ]; then
|
||||
uncompress -c $1 > $2
|
||||
else
|
||||
uncompress $1
|
||||
fi
|
||||
;;
|
||||
*.7z)
|
||||
if [ "$2" ]; then
|
||||
7z x $1 -o$2
|
||||
else
|
||||
7z x $1
|
||||
fi
|
||||
;;
|
||||
*) echo "don't know how to extract '$1'..." ;;
|
||||
esac
|
||||
else
|
||||
echo "'$1' is not a valid file!"
|
||||
fi
|
75
bin/git-cleaner
Executable file
75
bin/git-cleaner
Executable file
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
function help() {
|
||||
cat <<HELP
|
||||
Git Clean
|
||||
https://jonathanh.co.uk
|
||||
|
||||
Some code came from Ben Alman
|
||||
http://benalman.com/
|
||||
|
||||
|
||||
Usage: $(basename "$0") [command]
|
||||
|
||||
Commands:
|
||||
clean Remove current unstaged changes/untracked files**
|
||||
cleanall Remove all saved tags, unstaged changes and untracked files**
|
||||
|
||||
** This action is destructive and cannot be undone!
|
||||
|
||||
Description:
|
||||
Cleans unstaged changes and untracked files
|
||||
|
||||
Copyright (c) 2014 "Cowboy" Ben Alman
|
||||
Licensed under the MIT license.
|
||||
http://benalman.com/about/license/
|
||||
HELP
|
||||
}
|
||||
|
||||
function usage() {
|
||||
echo "Usage: $(basename "$0") [clean | cleanall]"
|
||||
}
|
||||
|
||||
function git_head_sha() {
|
||||
git rev-parse --short HEAD
|
||||
}
|
||||
|
||||
# Get absolute path to root of Git repo
|
||||
function git_repo_toplevel() {
|
||||
git rev-parse --show-toplevel
|
||||
}
|
||||
|
||||
# Clean (permanently) current changes and remove the current saved tag
|
||||
function clean() {
|
||||
local head_sha=$(git_head_sha)
|
||||
git tag -d "git-jump-$head_sha" &>/dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
echo "Removed stored data for commit $head_sha."
|
||||
fi
|
||||
local repo_root="$(git_repo_toplevel)"
|
||||
git reset HEAD "$repo_root" >/dev/null
|
||||
git clean -f -d -q -- "$repo_root" >/dev/null
|
||||
git checkout -- "$repo_root" >/dev/null
|
||||
echo "Unstaged changes and untracked files removed."
|
||||
}
|
||||
|
||||
# Remove (permanently) all saved tags
|
||||
function clean_all_tags() {
|
||||
git for-each-ref refs/tags --format='%(refname:short)' | \
|
||||
while read tag; do
|
||||
if [[ "$tag" =~ ^git-jump- ]]; then
|
||||
git tag -d "$tag"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Handle CLI arguments
|
||||
if [[ "$1" == "clean" ]]; then
|
||||
clean
|
||||
elif [[ "$1" == "cleanall" ]]; then
|
||||
clean_all_tags
|
||||
clean
|
||||
else
|
||||
usage
|
||||
exit 1
|
||||
fi
|
24
bin/git-delete-submodule
Executable file
24
bin/git-delete-submodule
Executable file
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
test -z "$1" && echo "submodule required" 1>&2 && exit 1
|
||||
#cd "$(git root)"
|
||||
test ! -f .gitmodules && echo ".gitmodules file not found" 1>&2 && exit 2
|
||||
|
||||
NAME="$(echo "$1" | sed 's/\/$//g')"
|
||||
test -z \
|
||||
"$(git config --file=.gitmodules submodule."$NAME".url)" \
|
||||
&& echo "submodule not found" 1>&2 && exit 3
|
||||
|
||||
# 1. Delete the relevant section from .git/config and clean submodule files
|
||||
git submodule deinit -f "$NAME" || exit 4
|
||||
rmdir "$NAME"
|
||||
rm -rf .git/modules/"$NAME"
|
||||
# 2. Delete the relevant line from .gitmodules
|
||||
git config --file=.gitmodules --remove-section submodule."$NAME"
|
||||
git add .gitmodules
|
||||
# 3. Run git rm --cached path_to_submodule
|
||||
git rm --cached -rf "$NAME"
|
||||
# 4. Need to confirm and commit the changes for yourself
|
||||
echo
|
||||
echo "Now submodule $NAME is deleted."
|
||||
echo 'Confirm with `git submodule status` and commit the changes for yourself.'
|
158
bin/git-jump
Executable file
158
bin/git-jump
Executable file
|
@ -0,0 +1,158 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
function help() {
|
||||
cat <<HELP
|
||||
Git Jump (Forward & Back)
|
||||
http://benalman.com/
|
||||
|
||||
Modified slightly by Jonathan Hodgson
|
||||
https://jonathanh.co.uk/
|
||||
|
||||
Copyright (c) 2017 Jonathan Hodgson
|
||||
Licensed under the MIT license.
|
||||
https://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
Usage: $(basename "$0") [command]
|
||||
|
||||
Commands:
|
||||
next Jump forward to the next commit in this branch
|
||||
prev Jump backward to the next commit in this branch
|
||||
|
||||
|
||||
Git config:
|
||||
git-jump.branch Branch to jump through. If not set, defaults to master
|
||||
|
||||
Description:
|
||||
"Replay" Git commits by moving forward / backward through a branch's
|
||||
history. Before jumping, any current unstaged changes and untracked
|
||||
files are saved in a tag for later retrieval, which is restored when
|
||||
jumped back to.
|
||||
|
||||
Original Licence:
|
||||
Copyright (c) 2014 "Cowboy" Ben Alman
|
||||
Licensed under the MIT license.
|
||||
http://benalman.com/about/license/
|
||||
HELP
|
||||
}
|
||||
|
||||
function usage() {
|
||||
echo "Usage: $(basename "$0") [next | prev]"
|
||||
}
|
||||
|
||||
# Get branch stored in Git config or default to master
|
||||
git_branch="$(git config git-jump.branch || echo "master")"
|
||||
|
||||
# Get some (short) SHAs
|
||||
function git_branch_sha() {
|
||||
git rev-parse --short "$git_branch"
|
||||
}
|
||||
function git_head_sha() {
|
||||
git rev-parse --short HEAD
|
||||
}
|
||||
function git_prev_sha() {
|
||||
git log --format='%h' "$git_branch" "$@" | awk "/^$(git_head_sha)/{getline; print}"
|
||||
}
|
||||
function git_next_sha() {
|
||||
git_prev_sha --reverse
|
||||
}
|
||||
|
||||
# Get absolute path to root of Git repo
|
||||
function git_repo_toplevel() {
|
||||
git rev-parse --show-toplevel
|
||||
}
|
||||
|
||||
# Get subject of specified commit
|
||||
function git_commit_subject() {
|
||||
git log --format='%s' -n 1 $1
|
||||
}
|
||||
|
||||
# Save changes for later retrieval
|
||||
function save() {
|
||||
local status=""
|
||||
local head_sha=$(git_head_sha)
|
||||
# Checkout current HEAD by SHA to force detached state
|
||||
git checkout -q $head_sha
|
||||
# Add all files in repo
|
||||
git add "$(git_repo_toplevel)"
|
||||
# Commit changes (if there were any)
|
||||
git commit --no-verify -m "Git Jump: saved changes for $head_sha" >/dev/null
|
||||
# If the commit was successful, tag it (overwriting any previous tag)
|
||||
if [[ $? == 0 ]]; then
|
||||
status="*"
|
||||
git tag -f "git-jump-$head_sha" >/dev/null
|
||||
fi
|
||||
echo "Previous HEAD was $head_sha$status, $(git_commit_subject $head_sha)"
|
||||
}
|
||||
|
||||
# Restore previously-saved changes
|
||||
function restore() {
|
||||
local status=""
|
||||
# Save current changes before restoring
|
||||
save
|
||||
# Attempt to restore saved changes for specified commit
|
||||
git checkout "git-jump-$1" 2>/dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
# If the restore was successful, figure out exactly what was saved, check
|
||||
# out the original commit, then restore the saved changes on top of it
|
||||
status="*"
|
||||
local patch="$(git format-patch HEAD^ --stdout)"
|
||||
git checkout HEAD^ 2>/dev/null
|
||||
echo "$patch" | git apply -
|
||||
else
|
||||
# Otherwise, just restore the original commit
|
||||
git checkout "$1" 2>/dev/null
|
||||
fi
|
||||
echo "HEAD is now $1$status, $(git_commit_subject $1)"
|
||||
}
|
||||
|
||||
# Jump to next commit
|
||||
function next() {
|
||||
local next_sha=$(git_next_sha)
|
||||
if [[ "$next_sha" == "$(git_head_sha)" ]]; then
|
||||
# Abort if no more commits
|
||||
echo "Already at last commit in $git_branch. Congratulations!"
|
||||
else
|
||||
# Checkout branch by name if at its HEAD
|
||||
if [[ "$next_sha" == "$(git_branch_sha)" ]]; then
|
||||
next_sha="$git_branch"
|
||||
fi
|
||||
echo "Jumping ahead to next commit."
|
||||
restore $next_sha
|
||||
fi
|
||||
}
|
||||
|
||||
# Jump to previous commit
|
||||
function prev() {
|
||||
local prev_sha=$(git_prev_sha)
|
||||
if [[ "$prev_sha" == "$(git_head_sha)" ]]; then
|
||||
# Abort if no more commits
|
||||
echo "Already at first commit in $git_branch."
|
||||
else
|
||||
echo "Jumping back to previous commit."
|
||||
restore $prev_sha
|
||||
fi
|
||||
}
|
||||
|
||||
# Show help if requested
|
||||
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
||||
help
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check if branch is valid
|
||||
git rev-parse "$git_branch" &>/dev/null
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Error: Branch \"$git_branch\" does not appear to be valid."
|
||||
echo "Try $(basename "$0") --help for more information."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Handle CLI arguments
|
||||
if [[ "$1" == "next" ]]; then
|
||||
next
|
||||
elif [[ "$1" == "prev" ]]; then
|
||||
prev
|
||||
else
|
||||
usage
|
||||
exit 1
|
||||
fi
|
12
bin/git-nuke
Executable file
12
bin/git-nuke
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Nukes a branch locally and on the origin remote.
|
||||
#
|
||||
# $1 - Branch name.
|
||||
#
|
||||
# Examples
|
||||
#
|
||||
# git nuke add-git-nuke
|
||||
|
||||
git branch -D $1
|
||||
git push origin :$1
|
149
bin/git-open
Executable file
149
bin/git-open
Executable file
|
@ -0,0 +1,149 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Opens the BitBucket/GitHub page for a repo/branch in your browser.
|
||||
#
|
||||
# git open
|
||||
# git open [remote] [branch]
|
||||
|
||||
|
||||
# are we in a git repo?
|
||||
git rev-parse --is-inside-work-tree &>/dev/null
|
||||
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Not a git repository." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# assume origin if not provided
|
||||
# fallback to upstream if neither is present.
|
||||
remote="origin"
|
||||
if [ -n "$1" ]; then
|
||||
if [ "$1" == "issue" ]; then
|
||||
currentBranch=$(git symbolic-ref -q --short HEAD)
|
||||
regex='^issue'
|
||||
if [[ $currentBranch =~ $regex ]]; then
|
||||
issue=${currentBranch#*#}
|
||||
else
|
||||
echo "'git open issue' expect branch naming to be issues/#123" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
remote="$1"
|
||||
fi
|
||||
fi
|
||||
|
||||
remote_url="remote.${remote}.url"
|
||||
|
||||
giturl=$(git config --get "$remote_url")
|
||||
if [ -z "$giturl" ]; then
|
||||
echo "$remote_url not set." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# get current branch
|
||||
if [ -z "$2" ]; then
|
||||
branch=$(git symbolic-ref -q --short HEAD)
|
||||
else
|
||||
branch="$2"
|
||||
fi
|
||||
|
||||
# Make # and % characters url friendly
|
||||
# github.com/paulirish/git-open/pull/24
|
||||
branch=${branch//%/%25} && branch=${branch//#/%23}
|
||||
|
||||
# URL normalization
|
||||
# GitHub gists
|
||||
if grep -q gist.github <<<$giturl; then
|
||||
giturl=${giturl/git\@gist.github\.com\:/https://gist.github.com/}
|
||||
providerUrlDifference=tree
|
||||
|
||||
# GitHub
|
||||
elif grep -q github <<<$giturl; then
|
||||
giturl=${giturl/git\@github\.com\:/https://github.com/}
|
||||
|
||||
# handle SSH protocol (links like ssh://git@github.com/user/repo)
|
||||
giturl=${giturl/#ssh\:\/\/git\@github\.com\//https://github.com/}
|
||||
|
||||
providerUrlDifference=tree
|
||||
|
||||
# Bitbucket
|
||||
elif grep -q bitbucket <<<$giturl; then
|
||||
giturl=${giturl/git\@bitbucket\.org\:/https://bitbucket.org/}
|
||||
# handle SSH protocol (change ssh://https://bitbucket.org/user/repo to https://bitbucket.org/user/repo)
|
||||
giturl=${giturl/#ssh\:\/\/git\@/https://}
|
||||
|
||||
rev="$(git rev-parse HEAD)"
|
||||
git_pwd="$(git rev-parse --show-prefix)"
|
||||
providerUrlDifference="src/${rev}/${git_pwd}"
|
||||
branch="?at=${branch}"
|
||||
|
||||
# Atlassian Bitbucket Server
|
||||
elif grep -q "/scm/" <<<$giturl; then
|
||||
re='(.*)/scm/(.*)/(.*)\.git'
|
||||
if [[ $giturl =~ $re ]]; then
|
||||
giturl=${BASH_REMATCH[1]}/projects/${BASH_REMATCH[2]}/repos/${BASH_REMATCH[3]}
|
||||
providerUrlDifference=browse
|
||||
branch="?at=refs%2Fheads%2F${branch}"
|
||||
fi
|
||||
|
||||
# GitLab
|
||||
else
|
||||
# custom GitLab
|
||||
gitlab_domain=$(git config --get gitopen.gitlab.domain)
|
||||
gitlab_ssh_domain=$(git config --get gitopen.gitlab.ssh.domain)
|
||||
gitlab_ssh_domain=${gitlab_ssh_domain:-$gitlab_domain}
|
||||
gitlab_ssh_port=$(git config --get gitopen.gitlab.ssh.port)
|
||||
|
||||
gitlab_protocol=$(git config --get gitopen.gitlab.protocol)
|
||||
if [ -z "$gitlab_protocol" ]; then
|
||||
gitlab_protocol=https
|
||||
fi
|
||||
|
||||
if [ -n "$gitlab_domain" ]; then
|
||||
if egrep -q "${gitlab_domain}|${gitlab_ssh_domain}" <<<$giturl; then
|
||||
|
||||
# Handle GitLab's default SSH notation (like git@gitlab.domain.com:user/repo)
|
||||
giturl=${giturl/git\@${gitlab_ssh_domain}\:/${gitlab_protocol}://${gitlab_domain}/}
|
||||
|
||||
# handle SSH protocol (links like ssh://git@gitlab.domain.com/user/repo)
|
||||
giturl=${giturl/#ssh\:\/\//${gitlab_protocol}://}
|
||||
|
||||
# remove git@ from the domain
|
||||
giturl=${giturl/git\@${gitlab_ssh_domain}/${gitlab_domain}/}
|
||||
|
||||
# remove SSH port
|
||||
if [ -n "$gitlab_ssh_port" ]; then
|
||||
giturl=${giturl/\/:${gitlab_ssh_port}\///}
|
||||
fi
|
||||
providerUrlDifference=tree
|
||||
fi
|
||||
# hosted GitLab
|
||||
elif grep -q gitlab <<<$giturl; then
|
||||
giturl=${giturl/git\@gitlab\.com\:/https://gitlab.com/}
|
||||
providerUrlDifference=tree
|
||||
fi
|
||||
fi
|
||||
giturl=${giturl%\.git}
|
||||
|
||||
if [ -n "$issue" ]; then
|
||||
giturl="${giturl}/issues/${issue}"
|
||||
elif [ -n "$branch" ]; then
|
||||
giturl="${giturl}/${providerUrlDifference}/${branch}"
|
||||
fi
|
||||
|
||||
# simplify URL for master
|
||||
giturl=${giturl/tree\/master/}
|
||||
|
||||
# get current open browser command
|
||||
case $( uname -s ) in
|
||||
Darwin) open=open;;
|
||||
MINGW*) open=start;;
|
||||
CYGWIN*) open=cygstart;;
|
||||
MSYS*) open="powershell.exe –NoProfile Start";;
|
||||
*) open=${BROWSER:-xdg-open};;
|
||||
esac
|
||||
|
||||
# open it in a browser
|
||||
$open "$giturl" &> /dev/null
|
||||
exit $?
|
349
bin/git-recall
Executable file
349
bin/git-recall
Executable file
|
@ -0,0 +1,349 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
# usage info
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: git recall [options]
|
||||
Options:
|
||||
-d, --date Show logs for last n days.
|
||||
-a, --author Author name.
|
||||
-f, --fetch fetch commits.
|
||||
-h, --help This message.
|
||||
-v, --version Show version.
|
||||
-- End of options.
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
# Global variables
|
||||
SINCE="1 days ago" # show logs for last day by default
|
||||
AUTHOR=""
|
||||
FETCH=false
|
||||
GIT_FORMAT=""
|
||||
GIT_LOG=""
|
||||
COMMITS=""
|
||||
COMMITS_UNCOL=() # commits without colors
|
||||
LESSKEY=false
|
||||
SED_BIN="" # Sed option to use according OS.
|
||||
VERSION="1.1.10"
|
||||
|
||||
# Are we in a git repo?
|
||||
if [[ ! -d ".git" ]] && ! git rev-parse --git-dir &>/dev/null; then
|
||||
echo "abort: not a git repository." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Parse options
|
||||
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do
|
||||
case $1 in
|
||||
-v | --version )
|
||||
echo "$version"
|
||||
exit
|
||||
;;
|
||||
-d | --date )
|
||||
SINCE="$2 days ago"
|
||||
shift;
|
||||
;;
|
||||
-a | --author )
|
||||
AUTHOR="$2"
|
||||
shift
|
||||
;;
|
||||
-f | --fetch )
|
||||
FETCH=true
|
||||
;;
|
||||
-h | --help )
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
* )
|
||||
echo "abort: unknown argument" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [[ "$1" == "--" ]]; then shift; fi
|
||||
|
||||
|
||||
# Colored output.
|
||||
function colored() {
|
||||
GREEN=$(tput setaf 4)
|
||||
YELLOW=$(tput setaf 3)
|
||||
NORMAL=$(tput sgr0)
|
||||
REVERSE=$(tput rev)
|
||||
}
|
||||
|
||||
# Uncolored output.
|
||||
function uncolored() {
|
||||
GREEN=""
|
||||
YELLOW=""
|
||||
NORMAL=""
|
||||
REVERSE=""
|
||||
}
|
||||
|
||||
# Enable colors if supported by terminal.
|
||||
if [[ -t 1 ]] && [[ -n "$TERM" ]] && which tput &>/dev/null && tput colors &>/dev/null; then
|
||||
ncolors=$(tput colors)
|
||||
if [[ -n "$ncolors" ]] && [[ "$ncolors" -ge 8 ]] ; then
|
||||
colored
|
||||
else
|
||||
uncolored
|
||||
fi
|
||||
else
|
||||
uncolored
|
||||
fi
|
||||
|
||||
# Check if lesskey is installed.
|
||||
if command -v lesskey &> /dev/null; then
|
||||
LESSKEY=true
|
||||
fi
|
||||
|
||||
# Set AUTHOR to current user if no param passed or display for all users if param equal to "all".
|
||||
if [[ ! -n $AUTHOR ]]; then
|
||||
AUTHOR=$(git config user.name 2>/dev/null)
|
||||
elif [[ $AUTHOR = "all" ]]; then
|
||||
AUTHOR=".*"
|
||||
fi
|
||||
|
||||
# Fetch changes before.
|
||||
if [[ $FETCH == true ]]; then
|
||||
echo "${GREEN}Fetching changes...${NORMAL}"
|
||||
git fetch --all &> /dev/null
|
||||
tput cuu1
|
||||
tput ed # clear screen
|
||||
fi
|
||||
|
||||
# Log template.
|
||||
GIT_FORMAT="%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset"
|
||||
|
||||
# Log command.
|
||||
GIT_LOG="git log --pretty=format:'${GIT_FORMAT}'
|
||||
--author \"$AUTHOR\"
|
||||
--since \"$SINCE\" --abbrev-commit"
|
||||
|
||||
# Change temporary the IFS to store GIT_LOG's output into an array.
|
||||
IFS=$'\n'
|
||||
COMMITS=($(eval ${GIT_LOG} 2>/dev/null))
|
||||
unset IFS
|
||||
|
||||
NI=${#COMMITS[@]} # Total number of items.
|
||||
SN=$(( `tput lines` - 1 )) # Screen's number of lines.
|
||||
CN=$(tput cols) # Screen's number of columns.
|
||||
TN=$(( $NI < $((SN -1)) ? $NI : $((SN -1)))) # Number of lines that we will display.
|
||||
OFFSET=0 #Incremented by one each time a commit's length is higher than teminal width.
|
||||
|
||||
# If there is no items, exit.
|
||||
if [[ $NI = 0 ]]; then
|
||||
if [[ $AUTHOR = ".*" ]]; then
|
||||
echo "${YELLOW}All contributors did nothing during this period.${NORMAL}" && exit 0
|
||||
else
|
||||
echo "${YELLOW}The contributor \"${AUTHOR}\" did nothing during this period.${NORMAL}" && exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set correct sed option according OS's type
|
||||
case "$OSTYPE" in
|
||||
darwin*) SED_BIN="sed -E" ;;
|
||||
*) SED_BIN="sed -r" ;;
|
||||
esac
|
||||
|
||||
# Create array with uncolred commits (removing escape sequences using sed)
|
||||
for elt in "${COMMITS[@]}"
|
||||
do
|
||||
ELT="$(echo "$elt" | $SED_BIN "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")" # remove colors escape codes
|
||||
COMMITS_UNCOL+=("$ELT")
|
||||
done
|
||||
# Add +1 to OFFSET if a commit's length is bigger than the current terminal session's width. (This is to fix a redraw issue)
|
||||
for C in "${COMMITS_UNCOL[@]}"
|
||||
do
|
||||
if [[ ${#C} -gt $CN ]]; then
|
||||
OFFSET=$(( OFFSET + 1 ))
|
||||
fi
|
||||
done
|
||||
|
||||
# Set keys.
|
||||
au="`echo -e '\e[A'`" # arrow up
|
||||
au_1="k" # arrow up
|
||||
ad="`echo -e '\e[B'`" # arrow down
|
||||
ad_1="j" # arrow down
|
||||
ec="`echo -e '\e'`" # escape
|
||||
nl="`echo -e '\n'`" # newline
|
||||
nl_1="e" # expand
|
||||
co="c" # checkout
|
||||
|
||||
# Create a temporary lesskey file to change the keybindings so the user can use the TAB key to quit less. (more convenient)
|
||||
if [[ $LESSKEY = true ]]; then
|
||||
echo "\t quit" | lesskey -o $HOME/.lsh_less_keys_tmp -- - &> /dev/null
|
||||
fi
|
||||
|
||||
## Get commit's diff.
|
||||
function get_diff() {
|
||||
ELT="$(echo "${COMMITS_UNCOL[$CP-1]}")"
|
||||
DIFF_TIP=${ELT:0:7}
|
||||
DIFF_CMD="git show $DIFF_TIP --color=always"
|
||||
DIFF=$(eval ${DIFF_CMD} 2>/dev/null)
|
||||
tmp_diff="$(echo "$DIFF" | $SED_BIN "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g")" # remove colors escape codes
|
||||
off=$(echo "$tmp_diff" | grep -c ".\{$CN\}") #Number of lines in the diff that are longer than terminal width.
|
||||
DIFF_LINES_NUMBER="$(echo "$DIFF" | wc -l)"
|
||||
DIFF_LINES_NUMBER=$(( DIFF_LINES_NUMBER + off ))
|
||||
}
|
||||
|
||||
## This function will print the diff according the commit's tip. If the diff is too long, the result will be displayed using 'less'.
|
||||
function print_diff() {
|
||||
get_diff # get commit's diff
|
||||
if [[ $(( TN + DIFF_LINES_NUMBER + OFFSET )) -ge $(( `tput lines` - 1 )) ]]; then
|
||||
if [[ $LESSKEY = true ]]; then
|
||||
echo "$DIFF" | less -r -k $HOME/.lsh_less_keys_tmp
|
||||
else
|
||||
echo "$DIFF" | less -r
|
||||
fi
|
||||
tput ed # Clear screen
|
||||
else
|
||||
stop=false
|
||||
tput ed
|
||||
for i in `seq 1 $TN`
|
||||
do
|
||||
echo -n "$NORMAL"
|
||||
[[ $CP == "$i" ]] && echo -n "$REVERSE"
|
||||
echo "${COMMITS[$i - 1]}"
|
||||
[[ $CP == "$i" ]] && echo "$DIFF"
|
||||
done
|
||||
# Wait for user action.
|
||||
while ! $stop
|
||||
do
|
||||
read -sn 1 key
|
||||
case "$key" in
|
||||
"$nl" | "$nl_1")
|
||||
stop=true
|
||||
;;
|
||||
"q")
|
||||
stop=true
|
||||
END=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
[[ $END = false ]] && tput cuu $(( TN + DIFF_LINES_NUMBER + OFFSET )) && tput ed
|
||||
[[ $END = true ]] && tput cuu 1
|
||||
fi
|
||||
}
|
||||
|
||||
function do_checkout(){
|
||||
ELT="$(echo "${COMMITS_UNCOL[$CP-1]}")"
|
||||
DIFF_TIP=${ELT:0:7}
|
||||
eval "git checkout $DIFF_TIP 2> /dev/null"
|
||||
}
|
||||
|
||||
# Calculate OFFSET to avoid bad redraw.
|
||||
function calculate_offset {
|
||||
tmp=1
|
||||
index=$(( SI -1 ))
|
||||
while [[ $tmp -lt $SN ]]
|
||||
do
|
||||
el=${COMMITS_UNCOL[$index]}
|
||||
if [[ ${#el} -gt $CN ]] && [[ $CP -lt $((SN -1)) ]]; then
|
||||
OFFSET_2=$(( OFFSET_2 + 1 ))
|
||||
tmp=$(( tmp + 1 ))
|
||||
fi
|
||||
tmp=$(( tmp + 1 ))
|
||||
index=$(( index + 1 ))
|
||||
done
|
||||
}
|
||||
|
||||
{ # capture stdout to stderr
|
||||
|
||||
tput civis # hide cursor.
|
||||
CP=1 # current position
|
||||
SI=1 # index
|
||||
END=false # end while loop
|
||||
EXT=0 # Used to extend the number of lines to display.
|
||||
|
||||
## Loops, reads inputs and prints commits until user presses 'q' to exit or TAB to show the diff.
|
||||
while ! $END
|
||||
do
|
||||
END_INDEX=0 # Index for the last item to display
|
||||
# When the number of item is higher than screen's number of lines, OFFSET_2 is recalculated each time we select a new item
|
||||
# Set last index to print. (based on OFFSET)
|
||||
if [[ $TN == $NI ]]; then
|
||||
END_INDEX=$TN
|
||||
OFFSET_2=$OFFSET
|
||||
elif [[ $TN == $(( SN - 1 )) ]]; then
|
||||
# Calculate new OFFSET.
|
||||
if [[ $OFFSET != 0 ]]; then
|
||||
[[ $CP -lt $((SN -1)) ]] && OFFSET_2=0
|
||||
EXT=1
|
||||
calculate_offset
|
||||
fi
|
||||
END_INDEX=$(( TN + SI -1 + EXT - OFFSET_2 ))
|
||||
fi
|
||||
|
||||
# Loop and echo commits
|
||||
for i in `seq $SI $END_INDEX`
|
||||
do
|
||||
echo -n "$NORMAL"
|
||||
[[ $CP == $i ]] && echo -n "$REVERSE"
|
||||
echo "${COMMITS[$i - 1]}"
|
||||
done
|
||||
|
||||
read -sn 1 key
|
||||
[[ "$key" == "$ec" ]] &&
|
||||
{
|
||||
read -sn 2 k2
|
||||
key="$key$k2"
|
||||
}
|
||||
|
||||
case "$key" in
|
||||
|
||||
"$au" | "$au_1")
|
||||
CP=$(( CP - 1 ))
|
||||
[[ $CP == 0 ]] && [[ $SI == 1 ]] && [[ $TN == $(( SN - 1 )) ]] && CP=$NI && SI=$(( NI - SN + 2 + OFFSET_2 ))
|
||||
[[ $CP == 0 ]] && [[ $SI == 1 ]] && [[ $TN == $NI ]] && CP=$TN
|
||||
[[ $CP == $(( SI - 1 )) ]] && [[ $SI != 1 ]] && SI=$(( SI - 1 ))
|
||||
|
||||
[[ $TN != $(( SN - 1 )) ]] && tput cuu $(( TN + OFFSET_2 ))
|
||||
[[ $TN == $(( SN - 1 )) ]] && tput cuu $(( TN + EXT ))
|
||||
[[ $SI != 1 ]] && tput ed # clear screen
|
||||
;;
|
||||
|
||||
"$ad" | "$ad_1")
|
||||
CP=$(( CP + 1 ))
|
||||
[[ $CP == $(( NI + 1 )) ]] && CP=1 && SI=1
|
||||
[[ $CP == $(( SN + SI - 1 + EXT - OFFSET_2 )) ]] && [[ $TN == $(( SN - 1 )) ]] && SI=$(( SI + 1 ))
|
||||
|
||||
[[ $TN != $(( SN - 1 )) ]] && tput cuu $(( TN + OFFSET_2 ))
|
||||
[[ $TN == $(( SN - 1 )) ]] && tput cuu $(( TN + EXT ))
|
||||
[[ $SI != 1 ]] && tput ed # clear screen
|
||||
[[ $SI = 1 ]] && [[ $CP = 1 ]] && tput ed # clear screen
|
||||
;;
|
||||
|
||||
"$nl" | "$nl_1")
|
||||
[[ $TN == $NI ]] && tput cuu $(( TN + OFFSET_2 ))
|
||||
[[ $TN != $NI ]] && tput cuu $(( TN + EXT ))
|
||||
print_diff
|
||||
;;
|
||||
"$co")
|
||||
si=false
|
||||
END=true
|
||||
do_checkout
|
||||
tput cuu 1 #move cursor up one line. (remove extra line)
|
||||
;;
|
||||
|
||||
"q")
|
||||
si=false
|
||||
END=true
|
||||
tput cuu 1 #move cursor up one line. (remove extra line)
|
||||
;;
|
||||
|
||||
* )
|
||||
tput cuu $(( TN + OFFSET_2 ))
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
# remove temporary less keybindings
|
||||
[[ $LESSKEY = true ]] && rm $HOME/.lsh_less_keys_tmp
|
||||
|
||||
tput cnorm # unhide cursor
|
||||
echo "$NORMAL" # normal colors
|
||||
|
||||
} >&2 # END capture
|
||||
|
364
bin/git-wtf
Executable file
364
bin/git-wtf
Executable file
|
@ -0,0 +1,364 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
HELP = <<EOS
|
||||
git-wtf displays the state of your repository in a readable, easy-to-scan
|
||||
format. It's useful for getting a summary of how a branch relates to a remote
|
||||
server, and for wrangling many topic branches.
|
||||
|
||||
git-wtf can show you:
|
||||
- How a branch relates to the remote repo, if it's a tracking branch.
|
||||
- How a branch relates to integration branches, if it's a feature branch.
|
||||
- How a branch relates to the feature branches, if it's an integration
|
||||
branch.
|
||||
|
||||
git-wtf is best used before a git push, or between a git fetch and a git
|
||||
merge. Be sure to set color.ui to auto or yes for maximum viewing pleasure.
|
||||
EOS
|
||||
|
||||
KEY = <<EOS
|
||||
KEY:
|
||||
() branch only exists locally
|
||||
{} branch only exists on a remote repo
|
||||
[] branch exists locally and remotely
|
||||
|
||||
x merge occurs both locally and remotely
|
||||
~ merge occurs only locally
|
||||
(space) branch isn't merged in
|
||||
|
||||
(It's possible for merges to occur remotely and not locally, of course, but
|
||||
that's a less common case and git-wtf currently doesn't display anything
|
||||
special for it.)
|
||||
EOS
|
||||
|
||||
USAGE = <<EOS
|
||||
Usage: git wtf [branch+] [options]
|
||||
|
||||
If [branch] is not specified, git-wtf will use the current branch. The possible
|
||||
[options] are:
|
||||
|
||||
-l, --long include author info and date for each commit
|
||||
-a, --all show all branches across all remote repos, not just
|
||||
those from origin
|
||||
-A, --all-commits show all commits, not just the first 5
|
||||
-s, --short don't show commits
|
||||
-k, --key show key
|
||||
-r, --relations show relation to features / integration branches
|
||||
--dump-config print out current configuration and exit
|
||||
|
||||
git-wtf uses some heuristics to determine which branches are integration
|
||||
branches, and which are feature branches. (Specifically, it assumes the
|
||||
integration branches are named "master", "next" and "edge".) If it guesses
|
||||
incorrectly, you will have to create a .git-wtfrc file.
|
||||
|
||||
To start building a configuration file, run "git-wtf --dump-config >
|
||||
.git-wtfrc" and edit it. The config file is a YAML file that specifies the
|
||||
integration branches, any branches to ignore, and the max number of commits to
|
||||
display when --all-commits isn't used. git-wtf will look for a .git-wtfrc file
|
||||
starting in the current directory, and recursively up to the root.
|
||||
|
||||
IMPORTANT NOTE: all local branches referenced in .git-wtfrc must be prefixed
|
||||
with heads/, e.g. "heads/master". Remote branches must be of the form
|
||||
remotes/<remote>/<branch>.
|
||||
EOS
|
||||
|
||||
COPYRIGHT = <<EOS
|
||||
git-wtf Copyright 2008--2009 William Morgan <wmorgan at the masanjin dot nets>.
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You can find the GNU General Public License at: http://www.gnu.org/licenses/
|
||||
EOS
|
||||
|
||||
require 'yaml'
|
||||
CONFIG_FN = ".git-wtfrc"
|
||||
|
||||
class Numeric; def pluralize s; "#{to_s} #{s}" + (self != 1 ? "s" : "") end end
|
||||
|
||||
if ARGV.delete("--help") || ARGV.delete("-h")
|
||||
puts USAGE
|
||||
exit
|
||||
end
|
||||
|
||||
## poor man's trollop
|
||||
$long = ARGV.delete("--long") || ARGV.delete("-l")
|
||||
$short = ARGV.delete("--short") || ARGV.delete("-s")
|
||||
$all = ARGV.delete("--all") || ARGV.delete("-a")
|
||||
$all_commits = ARGV.delete("--all-commits") || ARGV.delete("-A")
|
||||
$dump_config = ARGV.delete("--dump-config")
|
||||
$key = ARGV.delete("--key") || ARGV.delete("-k")
|
||||
$show_relations = ARGV.delete("--relations") || ARGV.delete("-r")
|
||||
ARGV.each { |a| abort "Error: unknown argument #{a}." if a =~ /^--/ }
|
||||
|
||||
## search up the path for a file
|
||||
def find_file fn
|
||||
while true
|
||||
return fn if File.exist? fn
|
||||
fn2 = File.join("..", fn)
|
||||
return nil if File.expand_path(fn2) == File.expand_path(fn)
|
||||
fn = fn2
|
||||
end
|
||||
end
|
||||
|
||||
want_color = `git config color.wtf`
|
||||
want_color = `git config color.ui` if want_color.empty?
|
||||
$color = case want_color.chomp
|
||||
when "true"; true
|
||||
when "auto"; $stdout.tty?
|
||||
end
|
||||
|
||||
def red s; $color ? "\033[31m#{s}\033[0m" : s end
|
||||
def green s; $color ? "\033[32m#{s}\033[0m" : s end
|
||||
def yellow s; $color ? "\033[33m#{s}\033[0m" : s end
|
||||
def cyan s; $color ? "\033[36m#{s}\033[0m" : s end
|
||||
def grey s; $color ? "\033[1;30m#{s}\033[0m" : s end
|
||||
def purple s; $color ? "\033[35m#{s}\033[0m" : s end
|
||||
|
||||
## the set of commits in 'to' that aren't in 'from'.
|
||||
## if empty, 'to' has been merged into 'from'.
|
||||
def commits_between from, to
|
||||
if $long
|
||||
`git log --pretty=format:"- %s [#{yellow "%h"}] (#{purple "%ae"}; %ar)" #{from}..#{to}`
|
||||
else
|
||||
`git log --pretty=format:"- %s [#{yellow "%h"}]" #{from}..#{to}`
|
||||
end.split(/[\r\n]+/)
|
||||
end
|
||||
|
||||
def show_commits commits, prefix=" "
|
||||
if commits.empty?
|
||||
puts "#{prefix} none"
|
||||
else
|
||||
max = $all_commits ? commits.size : $config["max_commits"]
|
||||
max -= 1 if max == commits.size - 1 # never show "and 1 more"
|
||||
commits[0 ... max].each { |c| puts "#{prefix}#{c}" }
|
||||
puts grey("#{prefix}... and #{commits.size - max} more (use -A to see all).") if commits.size > max
|
||||
end
|
||||
end
|
||||
|
||||
def ahead_behind_string ahead, behind
|
||||
[ahead.empty? ? nil : "#{ahead.size.pluralize 'commit'} ahead",
|
||||
behind.empty? ? nil : "#{behind.size.pluralize 'commit'} behind"].
|
||||
compact.join("; ")
|
||||
end
|
||||
|
||||
def widget merged_in, remote_only=false, local_only=false, local_only_merge=false
|
||||
left, right = case
|
||||
when remote_only; %w({ })
|
||||
when local_only; %w{( )}
|
||||
else %w([ ])
|
||||
end
|
||||
middle = case
|
||||
when merged_in && local_only_merge; green("~")
|
||||
when merged_in; green("x")
|
||||
else " "
|
||||
end
|
||||
print left, middle, right
|
||||
end
|
||||
|
||||
def show b
|
||||
have_both = b[:local_branch] && b[:remote_branch]
|
||||
|
||||
pushc, pullc, oosync = if have_both
|
||||
[x = commits_between(b[:remote_branch], b[:local_branch]),
|
||||
y = commits_between(b[:local_branch], b[:remote_branch]),
|
||||
!x.empty? && !y.empty?]
|
||||
end
|
||||
|
||||
if b[:local_branch]
|
||||
puts "Local branch: " + green(b[:local_branch].sub(/^heads\//, ""))
|
||||
|
||||
if have_both
|
||||
if pushc.empty?
|
||||
puts "#{widget true} in sync with remote"
|
||||
else
|
||||
action = oosync ? "push after rebase / merge" : "push"
|
||||
puts "#{widget false} NOT in sync with remote (you should #{action})"
|
||||
show_commits pushc unless $short
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if b[:remote_branch]
|
||||
puts "Remote branch: #{cyan b[:remote_branch]} (#{b[:remote_url]})"
|
||||
|
||||
if have_both
|
||||
if pullc.empty?
|
||||
puts "#{widget true} in sync with local"
|
||||
else
|
||||
action = pushc.empty? ? "merge" : "rebase / merge"
|
||||
puts "#{widget false} NOT in sync with local (you should #{action})"
|
||||
show_commits pullc unless $short
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
puts "\n#{red "WARNING"}: local and remote branches have diverged. A merge will occur unless you rebase." if oosync
|
||||
end
|
||||
|
||||
def show_relations b, all_branches
|
||||
ibs, fbs = all_branches.partition { |name, br| $config["integration-branches"].include?(br[:local_branch]) || $config["integration-branches"].include?(br[:remote_branch]) }
|
||||
if $config["integration-branches"].include? b[:local_branch]
|
||||
puts "\nFeature branches:" unless fbs.empty?
|
||||
fbs.each do |name, br|
|
||||
next if $config["ignore"].member?(br[:local_branch]) || $config["ignore"].member?(br[:remote_branch])
|
||||
next if br[:ignore]
|
||||
local_only = br[:remote_branch].nil?
|
||||
remote_only = br[:local_branch].nil?
|
||||
name = if local_only
|
||||
purple br[:name]
|
||||
elsif remote_only
|
||||
cyan br[:name]
|
||||
else
|
||||
green br[:name]
|
||||
end
|
||||
|
||||
## for remote_only branches, we'll compute wrt the remote branch head. otherwise, we'll
|
||||
## use the local branch head.
|
||||
head = remote_only ? br[:remote_branch] : br[:local_branch]
|
||||
|
||||
remote_ahead = b[:remote_branch] ? commits_between(b[:remote_branch], head) : []
|
||||
local_ahead = b[:local_branch] ? commits_between(b[:local_branch], head) : []
|
||||
|
||||
if local_ahead.empty? && remote_ahead.empty?
|
||||
puts "#{widget true, remote_only, local_only} #{name} #{local_only ? "(local-only) " : ""}is merged in"
|
||||
elsif local_ahead.empty?
|
||||
puts "#{widget true, remote_only, local_only, true} #{name} merged in (only locally)"
|
||||
else
|
||||
behind = commits_between head, (br[:local_branch] || br[:remote_branch])
|
||||
ahead = remote_only ? remote_ahead : local_ahead
|
||||
puts "#{widget false, remote_only, local_only} #{name} #{local_only ? "(local-only) " : ""}is NOT merged in (#{ahead_behind_string ahead, behind})"
|
||||
show_commits ahead unless $short
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "\nIntegration branches:" unless ibs.empty? # unlikely
|
||||
ibs.sort_by { |v, br| v }.each do |v, br|
|
||||
next if $config["ignore"].member?(br[:local_branch]) || $config["ignore"].member?(br[:remote_branch])
|
||||
next if br[:ignore]
|
||||
local_only = br[:remote_branch].nil?
|
||||
remote_only = br[:local_branch].nil?
|
||||
name = remote_only ? cyan(br[:name]) : green(br[:name])
|
||||
|
||||
ahead = commits_between v, (b[:local_branch] || b[:remote_branch])
|
||||
if ahead.empty?
|
||||
puts "#{widget true, local_only} merged into #{name}"
|
||||
else
|
||||
#behind = commits_between b[:local_branch], v
|
||||
puts "#{widget false, local_only} NOT merged into #{name} (#{ahead.size.pluralize 'commit'} ahead)"
|
||||
show_commits ahead unless $short
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#### EXECUTION STARTS HERE ####
|
||||
|
||||
## find config file and load it
|
||||
$config = { "integration-branches" => %w(heads/master heads/next heads/edge), "ignore" => [], "max_commits" => 5 }.merge begin
|
||||
fn = find_file CONFIG_FN
|
||||
if fn && (h = YAML::load_file(fn)) # yaml turns empty files into false
|
||||
h["integration-branches"] ||= h["versions"] # support old nomenclature
|
||||
h
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
if $dump_config
|
||||
puts $config.to_yaml
|
||||
exit
|
||||
end
|
||||
|
||||
## first, index registered remotes
|
||||
remotes = `git config --get-regexp ^remote\.\*\.url`.split(/[\r\n]+/).inject({}) do |hash, l|
|
||||
l =~ /^remote\.(.+?)\.url (.+)$/ or next hash
|
||||
hash[$1] ||= $2
|
||||
hash
|
||||
end
|
||||
|
||||
## next, index followed branches
|
||||
branches = `git config --get-regexp ^branch\.`.split(/[\r\n]+/).inject({}) do |hash, l|
|
||||
case l
|
||||
when /branch\.(.*?)\.remote (.+)/
|
||||
name, remote = $1, $2
|
||||
|
||||
hash[name] ||= {}
|
||||
hash[name].merge! :remote => remote, :remote_url => remotes[remote]
|
||||
when /branch\.(.*?)\.merge ((refs\/)?heads\/)?(.+)/
|
||||
name, remote_branch = $1, $4
|
||||
hash[name] ||= {}
|
||||
hash[name].merge! :remote_mergepoint => remote_branch
|
||||
end
|
||||
hash
|
||||
end
|
||||
|
||||
## finally, index all branches
|
||||
remote_branches = {}
|
||||
`git show-ref`.split(/[\r\n]+/).each do |l|
|
||||
sha1, ref = l.chomp.split " refs/"
|
||||
|
||||
if ref =~ /^heads\/(.+)$/ # local branch
|
||||
name = $1
|
||||
next if name == "HEAD"
|
||||
branches[name] ||= {}
|
||||
branches[name].merge! :name => name, :local_branch => ref
|
||||
elsif ref =~ /^remotes\/(.+?)\/(.+)$/ # remote branch
|
||||
remote, name = $1, $2
|
||||
remote_branches["#{remote}/#{name}"] = true
|
||||
next if name == "HEAD"
|
||||
ignore = !($all || remote == "origin")
|
||||
|
||||
branch = name
|
||||
if branches[name] && branches[name][:remote] == remote
|
||||
# nothing
|
||||
else
|
||||
name = "#{remote}/#{branch}"
|
||||
end
|
||||
|
||||
branches[name] ||= {}
|
||||
branches[name].merge! :name => name, :remote => remote, :remote_branch => "#{remote}/#{branch}", :remote_url => remotes[remote], :ignore => ignore
|
||||
end
|
||||
end
|
||||
|
||||
## assemble remotes
|
||||
branches.each do |k, b|
|
||||
next unless b[:remote] && b[:remote_mergepoint]
|
||||
b[:remote_branch] = if b[:remote] == "."
|
||||
b[:remote_mergepoint]
|
||||
else
|
||||
t = "#{b[:remote]}/#{b[:remote_mergepoint]}"
|
||||
remote_branches[t] && t # only if it's still alive
|
||||
end
|
||||
end
|
||||
|
||||
show_dirty = ARGV.empty?
|
||||
targets = if ARGV.empty?
|
||||
[`git symbolic-ref HEAD`.chomp.sub(/^refs\/heads\//, "")]
|
||||
else
|
||||
ARGV.map { |x| x.sub(/^heads\//, "") }
|
||||
end.map { |t| branches[t] or abort "Error: can't find branch #{t.inspect}." }
|
||||
|
||||
targets.each do |t|
|
||||
show t
|
||||
show_relations t, branches if $show_relations || t[:remote_branch].nil?
|
||||
end
|
||||
|
||||
modified = show_dirty && `git ls-files -m` != ""
|
||||
uncommitted = show_dirty && `git diff-index --cached HEAD` != ""
|
||||
|
||||
if $key
|
||||
puts
|
||||
puts KEY
|
||||
end
|
||||
|
||||
puts if modified || uncommitted
|
||||
puts "#{red "NOTE"}: working directory contains modified files." if modified
|
||||
puts "#{red "NOTE"}: staging area contains staged but uncommitted files." if uncommitted
|
||||
|
||||
# the end!
|
103
bin/imgcat
Executable file
103
bin/imgcat
Executable file
|
@ -0,0 +1,103 @@
|
|||
#!/bin/bash
|
||||
|
||||
# tmux requires unrecognized OSC sequences to be wrapped with DCS tmux;
|
||||
# <sequence> ST, and for all ESCs in <sequence> to be replaced with ESC ESC. It
|
||||
# only accepts ESC backslash for ST.
|
||||
function print_osc() {
|
||||
if [[ $TERM == screen* ]] ; then
|
||||
printf "\033Ptmux;\033\033]"
|
||||
else
|
||||
printf "\033]"
|
||||
fi
|
||||
}
|
||||
|
||||
# More of the tmux workaround described above.
|
||||
function print_st() {
|
||||
if [[ $TERM == screen* ]] ; then
|
||||
printf "\a\033\\"
|
||||
else
|
||||
printf "\a"
|
||||
fi
|
||||
}
|
||||
|
||||
# print_image filename inline base64contents
|
||||
# filename: Filename to convey to client
|
||||
# inline: 0 or 1
|
||||
# base64contents: Base64-encoded contents
|
||||
function print_image() {
|
||||
print_osc
|
||||
printf '1337;File='
|
||||
if [[ -n "$1" ]]; then
|
||||
printf 'name='`echo -n "$1" | base64`";"
|
||||
fi
|
||||
if $(base64 --version 2>&1 | grep GNU > /dev/null)
|
||||
then
|
||||
BASE64ARG=-d
|
||||
else
|
||||
BASE64ARG=-D
|
||||
fi
|
||||
echo -n "$3" | base64 $BASE64ARG | wc -c | awk '{printf "size=%d",$1}'
|
||||
printf ";inline=$2"
|
||||
printf ";width=50"
|
||||
printf ":"
|
||||
echo -n "$3"
|
||||
print_st
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
function error() {
|
||||
echo "ERROR: $*" 1>&2
|
||||
}
|
||||
|
||||
function show_help() {
|
||||
echo "Usage: imgcat filename ..." 1>& 2
|
||||
echo " or: cat filename | imgcat" 1>& 2
|
||||
}
|
||||
|
||||
## Main
|
||||
|
||||
if [ -t 0 ]; then
|
||||
has_stdin=f
|
||||
else
|
||||
has_stdin=t
|
||||
fi
|
||||
|
||||
# Show help if no arguments and no stdin.
|
||||
if [ $has_stdin = f -a $# -eq 0 ]; then
|
||||
show_help
|
||||
exit
|
||||
fi
|
||||
|
||||
# Look for command line flags.
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h|--h|--help)
|
||||
show_help
|
||||
exit
|
||||
;;
|
||||
-*)
|
||||
error "Unknown option flag: $1"
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
if [ -r "$1" ] ; then
|
||||
print_image "$1" 1 "$(base64 < "$1")"
|
||||
else
|
||||
error "imgcat: $1: No such file or directory"
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Read and print stdin
|
||||
if [ $has_stdin = t ]; then
|
||||
print_image "" 1 "$(cat | base64)"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo
|
||||
|
||||
exit 0
|
91
bin/new
Executable file
91
bin/new
Executable file
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
if [ $1 ]; then
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
echo "Create files from template"
|
||||
echo ""
|
||||
echo "Usage: new [options] newFile"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo "--------"
|
||||
echo -e "{-t,--template} filename \t Force use of template in Template Directory"
|
||||
echo -e "{-l,--list} \t\t\t Lists the available templates"
|
||||
echo -e "{-h,--help} \t\t\t Show this help text"
|
||||
exit 0
|
||||
;;
|
||||
-t|--template)
|
||||
shift
|
||||
if [[ -f "$HOME/Templates/$1" ]]; then
|
||||
template="$HOME/Templates/$1"
|
||||
else
|
||||
echo "The file $HOME/Templates/$1 does not exits"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
-l|--list)
|
||||
shift
|
||||
for file in $HOME/Templates/*$1; do
|
||||
echo ${file##*/}
|
||||
done
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
file=$1
|
||||
if [[ "$template" == "" ]]; then
|
||||
extention=${file##*.}
|
||||
posTemplates=()
|
||||
if [[ -f $HOME/Templates/$extention ]]; then
|
||||
posTemplates+=("$HOME/Templates/$extention")
|
||||
fi
|
||||
for template in $HOME/Templates/*.$extention; do
|
||||
if [[ -f $template ]]; then
|
||||
posTemplates+=( $template )
|
||||
fi
|
||||
done
|
||||
if [[ ${#posTemplates[@]} == 1 ]]; then
|
||||
echo "Only one template"
|
||||
template=${posTemplates[0]}
|
||||
else
|
||||
|
||||
posTemplates+=("Cancel")
|
||||
while
|
||||
echo Your options are:
|
||||
for (( i=0; i<${#posTemplates[@]}; i++ )); do
|
||||
echo "$i: ${posTemplates[$i]##*/}"
|
||||
done
|
||||
echo -e -n "Please enter a number: [0] "
|
||||
read input
|
||||
if [[ "$input"=="" ]]; then
|
||||
test=0
|
||||
fi;
|
||||
if [[ "$input" == "$(expr ${#posTemplates[@]} - 1)" ]]; then
|
||||
echo "Exited By User"
|
||||
exit 0
|
||||
fi
|
||||
template=${posTemplates[$input]}
|
||||
[[ $input>=${#posTemplates[@]} || $input<0 ]]
|
||||
do
|
||||
echo
|
||||
echo Please chose one of the available options
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [[ -f "$file" ]]; then
|
||||
echo "$file already exists"
|
||||
echo "delete it first"
|
||||
exit 1
|
||||
fi
|
||||
cat "$template" > "$file"
|
||||
echo "$file created from template $template"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
echo "You haven't given anything to work with"
|
||||
fi
|
31
bin/php-swap
Executable file
31
bin/php-swap
Executable file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/bash
|
||||
line=$(php --version | grep "PHP" -m 1)
|
||||
target="$1"
|
||||
lampp='/opt/lampp/lampp'
|
||||
echo $phpexe
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "Sorry, you are not root."
|
||||
exit 1
|
||||
fi
|
||||
if [[ $target = "" ]]; then
|
||||
echo "PLease specify the version you want"
|
||||
exit 1
|
||||
fi;
|
||||
|
||||
file="/opt/lampp/etc/extra/httpd-xampp-php$target.conf"
|
||||
phpexe=$(ls /opt/lampp/bin/php-$target*)
|
||||
phpcgi=$(ls /opt/lampp/bin/php-cgi-$target*)
|
||||
phpconfig=$(ls /opt/lampp/bin/php-config-$target*)
|
||||
phpize=$(ls /opt/lampp/bin/phpize-$target*)
|
||||
|
||||
$lampp stopapache
|
||||
ln -s -f $file /opt/lampp/etc/extra/httpd-xampp.conf
|
||||
ln -s -f $phpexe /opt/lampp/bin/php
|
||||
ln -s -f $phpcgi /opt/lampp/bin/php-cgi
|
||||
ln -s -f $phpconfig /opt/lampp/bin/php-config
|
||||
ln -s -f $phpize /opt/lampp/bin/phpize
|
||||
|
||||
$lampp startapache
|
||||
echo
|
||||
echo "Now on PHP $target"
|
||||
exit 0
|
8
bin/update3rdPartyPlugins
Executable file
8
bin/update3rdPartyPlugins
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/bash
|
||||
|
||||
pluginFolder="/home/jonathan/WPPlugins"
|
||||
for dir in $pluginFolder/*/; do
|
||||
cd $dir
|
||||
pwd | cowsay
|
||||
git-svn-mirror update
|
||||
done
|
7
bin/weather
Executable file
7
bin/weather
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/bash
|
||||
initial=$@
|
||||
place=${initial// /+}
|
||||
if [[ "$place" == "" ]]; then
|
||||
place="Bury+St+Edmunds"
|
||||
fi
|
||||
curl "wttr.in/$place"
|
2
bin/where
Executable file
2
bin/where
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/bash
|
||||
find . -name "$1" | sed 's/[^/]\+$//' | uniq -c | sort -g
|
Loading…
Add table
Add a link
Reference in a new issue