This repository was archived by the owner on Jun 28, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathgitc
executable file
·232 lines (188 loc) · 6.72 KB
/
gitc
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#!/bin/bash
set -e
if [[ ! $GIT_CACHE_DIR ]]; then
GIT_CACHE_DIR=$HOME/.gitobjectstore
fi
# Helper functions.
# ----------------------------------------------------------------------------
function __gitc_filter_args() {
local args=
while test $# != 0; do
case "$1" in
--store-group) shift ;;
*) args+=" $1" ;;
esac; shift
done
echo $args
}
function __gitc_initialize() {
__GITC_PROJECT=
__GITC_DOMAIN=
__GITC_CACHE_DIR=
local args=
local grou='default'
while test $# != 0; do
case "$1" in
--store-group) grou="$2"; shift ;;
*) args+=" $1" ;;
esac; shift
done
set - $args
# 1 addr - full address
# | 2 prot - protocol, e.g. http://, git://, etc...
# | | 3 user - the user in [email protected][...]
# | | | 4 doma - domain, e.g. git.drupal.org
# | | | | 5 port - port number
# | | | | | 6 path - path after domain
# | | | | | | 7 proj - project name
# | | | | | | |
local s=$(echo "~ $*"| sed -n 's|.*[ ]\(\([a-zA-Z]*://\)*\([^ ]*[@]\)*\([^ /:]*\)[:]*\([0-9]*\)*[/]*\([^ :]*[^ /]*/\([^ /]*\)\.git\)\).*|\1,\2,\3,\4,\5,\6,\7|p')
local addr=$(echo $s | sed -n 's|\([^,]*\),.*|\1|p')
local prot=$(echo $s | sed -n 's|\([^,]*,\)\{1\}\([^,]*\),.*|\2|p')
local user=$(echo $s | sed -n 's|\([^,]*,\)\{2\}\([^,@]*\)[@]*,.*|\2|p')
local doma=$(echo $s | sed -n 's|\([^,]*,\)\{3\}\([^,]*\),.*|\2|p')
local port=$(echo $s | sed -n 's|\([^,]*,\)\{4\}\([^,]*\),.*|\2|p')
local path=$(echo $s | sed -n 's|\([^,]*,\)\{5\}\([^,]*\),.*|\2|p')
local proj=$(echo $s | sed -n 's|\([^,]*,\)\{6\}\([^,]*\)|\2|p')
local repo=
local cdir=
local cwd=`pwd`
if [[ $doma ]]; then
__GITC_PROJECT=$proj
__GITC_DOMAIN=$doma
__GITC_CACHE_DIR=$GIT_CACHE_DIR/$grou
cdir=$__GITC_CACHE_DIR
else
echo "Could not determine the url for the repository." && exit
fi
# Create cache directory for the domain and initialize if it doesn't exist.
if [[ ! -d $cdir ]]; then
mkdir $cdir && cd $cdir
git init --bare
# Object store should never be pruned.
git config --add gc.pruneexpire never
# Remove the initialized repo on failure.
# 1/SIGHUP, 2/SIGINT, 3/SIGQUIT, 15/SIGTERM, ERR
trap "rm -Rf $cdir && cd $cwd" 1 2 3 15 ERR
else
cd $cdir
fi
# If the remote doesn't exist locally, then initialize.
if [[ ! `git remote | sed -n "/^${proj}$/p"` ]]; then
# Create a temporary directory.
if [[ -d $TMPDIR ]]; then
TEMPDIR=`mktemp -d -t $proj`
else
TEMPDIR=`mktemp -d`
fi
trap "rm -Rf $TEMPDIR && cd $cwd" EXIT
# Clone to a temporary directory and update the cache store from there.
echo "Initialized clone of $proj from $doma..."
git clone --bare $addr $TEMPDIR
git remote add $proj $TEMPDIR
# Add default configuration for the project.
# Do not download tags due to the overlaps across projects.
git config --add remote.$proj.tagopt --no-tags
# Update with temporary clone then point remote URL externally.
echo "Creating cache: $doma >> $proj..."
git remote update $proj
git remote set-url $proj $addr
git fetch $proj
fi
cd $cwd
}
function ___gitc_fetch_object_store() {
local cwd=`pwd`
local cdir=`__gitc_cache_dir`
local proj=`__gitc_project`
if [[ -d $cdir && -n $proj ]]; then
cd $cdir
echo "Fetching object store..." && git fetch $proj
cd $cwd
fi
}
function __gitc_alternates() {
echo "`git rev-parse --show-toplevel`/.git/objects/info/alternates"
}
function __gitc_is_cached() {
__gitc_cache_dir
}
function __gitc_cache_dir() {
git config -z --get git-cached.cache-dir 2> /dev/null
}
function __gitc_project() {
git config -z --get git-cached.project 2> /dev/null
}
function __gitc_domain() {
git config -z --get git-cached.domain 2> /dev/null
}
# Callback functions.
# ----------------------------------------------------------------------------
function _gitc_fetch() {
___gitc_fetch_object_store
git "$@"
}
function _gitc_pull() {
_gitc_fetch "$@"
}
function _gitc_cclone() {
set - `__gitc_filter_args "$@"`
__gitc_initialize "$@"
# Add tracking info.
local config=
config+=" --config git-cached.project=$__GITC_PROJECT"
config+=" --config git-cached.domain=$__GITC_DOMAIN"
config+=" --config git-cached.cache-dir=$__GITC_CACHE_DIR"
shift
git clone "$@" --reference $__GITC_CACHE_DIR $config
}
function _gitc_cache_attach() {
[[ -n `__gitc_is_cached` ]] && echo "Already attached." && exit
set - `__gitc_filter_args "$@"`
__gitc_initialize `git config --get remote.origin.url` "$@"
git config --replace-all git-cached.project $__GITC_PROJECT
git config --replace-all git-cached.domain $__GITC_DOMAIN
git config --replace-all git-cached.cache-dir $__GITC_CACHE_DIR
local cdir=`__gitc_cache_dir`
local alts=`__gitc_alternates`
# Point to cached object dir inside the alternates file.
echo $cdir/objects >> $alts
echo "Taking out the garbage..." && git gc
}
function _gitc_cache_detach() {
[[ -z `__gitc_is_cached` ]] && echo "Nothing to detach." && exit
local cdir=`__gitc_cache_dir`
local alts=`__gitc_alternates`
echo "Repacking..." && git repack -a -d -l
# Remove object pointer. An 'alternates.bak' will be created.
sed -i.bak "s|^$cdir/objects$||" $alts
git config -z --remove-section git-cached 2> /dev/null
}
function _gitc_cache_repair() {
echo "Repairing..." && _gitc_cache_detach && _gitc_cache_attach "$@"
}
# Don't use this if the alternates file was manually modified.
function _gitc_overwrite_alternates() {
local cdir=`__gitc_cache_dir`
local alts=`__gitc_alternates`
if [[ -n `__gitc_is_cached` && -d $cdir/objects ]]; then
echo $cdir/objects > $alts && echo "Alternates pointing to $cdir"
else
echo "Does not use shared object storage."
fi
}
function _gitc_cache() {
local cwd=`pwd`
local cdir=`__gitc_cache_dir`
if [[ -d $cdir ]]; then
shift && cd $cdir && git "$@" && cd $cwd
else
echo "Git object store does not exist."
fi
}
# Callback
# ----------------------------------------------------------------------------
# Detect callback function and fallback to git if it doesn't exist.
__callback="_gitc_${1//-/_}"
# Filter out flags.
[[ ! $1 =~ ^-.* && `declare -Ff $__callback` ]] && $__callback "$@" || git "$@"