forked from firetech/dotfiles
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path.update.zsh
140 lines (120 loc) · 3.68 KB
/
.update.zsh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#
# Dotfiles automatic update by Joakim Tufvegren
#
# This is run automatically by ~/.zshrc once per $update_limit days or manually
# by running update_dotfiles.
# Some minor inspiration from oh-my-zsh's upgrade code.
#
setopt nonomatch
zshrc=$HOME/.zshrc
repo=${zshrc:A:h:h}
timestamp_file=$repo/.update_timestamp
update_limit=14
branch=origin/master
exit_status=0
__log_print() {
local pre="[update_dotfiles] " post
if [[ $TERM != dumb ]]; then
pre="\e[01;34m$pre\e[00;${1}m"
post="\e[00m"
fi
shift
for x in $@; echo $pre$x$post
}
_log_info() {
__log_print 32 $@
}
_log_warn() {
__log_print 33 $@ >&2
}
_log_error() {
__log_print 31 $@ >&2
}
_fatal() {
_log_error $@
exit 1
}
_current_day() {
echo $(($(date +%s) / 60 / 60 / 24))
}
_update_timestamp() {
local t=$1
[[ -z $t ]] && t=$(_current_day)
[[ -f $timestamp_file ]] || touch $timestamp_file
echo "timestamp=$t" >| $timestamp_file
}
if [[ $1 == defer ]]; then
_log_info "Deferring update check for next ZSH launch."
_update_timestamp 0
exit 0
elif [[ $1 == auto ]]; then
# Running automatically from ~/.zshrc.
if [[ -f $timestamp_file ]]; then
source $timestamp_file
if [[ -z $timestamp ]]; then
_update_timestamp
exit 0
fi
else
_update_timestamp
exit 0
fi
[[ $(($(_current_day) - $timestamp)) -lt $update_limit ]] && exit 0
elif [[ $# -gt 0 ]]; then
_fatal "Unknown argument '$1'"
fi
if [[ ! -x =git ]]; then
_update_timestamp
_fatal "Can't upgrade, no git found."
fi
if [[ ! -d $repo/.git ]]; then
_update_timestamp
_fatal "Can't upgrade, '$repo' is not a git repo."
fi
cd $repo
commits_ahead=$( (git log --oneline $branch..HEAD | wc -l) || \
_fatal "Checking number of commits ahead failed." )
commits_ahead=${commits_ahead// /}
[[ $commits_ahead -gt 0 ]] && \
_log_warn "Found $commits_ahead unpushed commit(s)."
uncommitted_files=$( (git status --porcelain | wc -l) || \
_fatal "Checking git file status failed." )
uncommitted_files=${uncommitted_files// /}
[[ $uncommitted_files -gt 0 ]] && \
_log_warn "Found $uncommitted_files uncommitted file(s)."
_log_info "Checking for updates..."
git fetch -q || \
_fatal "Fetching from git server failed."
commits_behind=$( (git log --oneline HEAD..$branch | wc -l) || \
_fatal "Checking number of commits behind failed." )
commits_behind=${commits_behind// /}
if [[ $commits_behind -gt 0 ]]; then
file_list_pre=$(ls config)
_log_info "Found $commits_behind new commits. Updating..."
git rebase -q $branch || \
_fatal "Updating failed." "Manual merge in '$repo' needed."
_log_info "Update successful."
if [[ $file_list_pre != $(ls config) ]]; then
file_list_diff=$(ls config | diff --unchanged-line-format= \
--new-line-format='+ .%L' \
--old-line-format='- .%L' \
=(echo $file_list_pre) -)
# Separate and split lines into array
file_list_new=(${(f)"$(echo $file_list_diff | grep '^+')"})
file_list_rm=(${(f)"$(echo $file_list_diff | grep '^-')"})
if [[ -n $file_list_new ]]; then
_log_warn "New files:" $file_list_new
_log_info "Re-running install script..."
$repo/install || _log_error "Install script failed!"
fi
if [[ -n $file_list_rm ]]; then
_log_warn "Removed files:" $file_list_rm \
"You may want to remove these symlinks."
fi
fi
# Signal to reload zsh config
exit_status=0x8
fi
_update_timestamp
[[ $exit_status -eq 0x8 ]] && _log_info "Reloading ZSH config..."
exit $exit_status