Skip to content

Commit 8e3d95d

Browse files
committed
Interactive staging and better init.
1 parent 37bde1e commit 8e3d95d

File tree

1 file changed

+95
-38
lines changed

1 file changed

+95
-38
lines changed

bash/dcs/dcs

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@ source bashlib
44

55
# Utilities.
66
gitg() {
7+
[[ -e "$dcs/git.global" ]] || ftl 'Missing global DCS repository at %s' "$dcs" || exit
8+
(( ! $# )) && return
9+
710
GIT_DIR="$dcs/git.global" \
811
GIT_WORK_TREE="$workdir" \
912
command git "$@"
1013
}
1114
gitl() {
15+
[[ -e "$dcs/git.local" ]] || ftl 'Missing local DCS repository at %s' "$dcs" || exit
16+
(( ! $# )) && return
17+
1218
GIT_DIR="$dcs/git.local" \
1319
GIT_ALTERNATE_OBJECT_DIRECTORIES="$dcs/git.global/objects" \
1420
GIT_WORK_TREE="$workdir" \
@@ -32,37 +38,19 @@ githas() {
3238
ogithas() {
3339
ogit ls-files --error-unmatch "$@" >/dev/null 2>&1
3440
}
41+
updateRepos() {
42+
# Ensure both repos are available
43+
gitg && gitl
3544

45+
# Ensure we're on the right branch
46+
if [[ $(gitg symbolic-ref --short HEAD) != $branch_global ]]; then
47+
gitg checkout -B "$branch_global"
48+
fi
49+
if [[ $(gitl symbolic-ref --short HEAD) != $branch_local ]]; then
50+
gitl checkout -B "$branch_local"
51+
fi
3652

37-
# Initialize our working directory.
38-
workdir=$(
39-
default=$PWD
40-
until [[ -e .dcs.d || $PWD = / ]]; do cd ..; done
41-
[[ -e .dcs.d ]] && echo "$PWD" || echo "$default"
42-
)
43-
dcs=$workdir/.dcs.d
44-
if [[ ! -e "$dcs" ]]; then
45-
[[ $(ask -c Ny 'Initialize DCS in %s?' "$workdir") = y ]] || exit
46-
mkdir -p "$dcs"
47-
fi
48-
branch_global=global/master
49-
branch_local=local/${HOSTNAME%%.*}
50-
if [[ ! -e "$dcs/git.global" ]]; then
51-
command git init --bare "$dcs/git.global"
52-
echo "ref: refs/heads/$branch_global" > "$dcs/git.global/HEAD"
53-
elif [[ $(gitg symbolic-ref --short HEAD) != $branch_global ]]; then
54-
gitg checkout -B "$branch_global"
55-
fi
56-
if [[ ! -e "$dcs/git.local" ]]; then
57-
command git init --bare "$dcs/git.local"
58-
echo "ref: refs/heads/$branch_local" > "$dcs/git.local/HEAD"
59-
elif [[ $(gitl symbolic-ref --short HEAD) != $branch_local ]]; then
60-
gitl checkout -B "$branch_local"
61-
fi
62-
63-
64-
# Update global and local exclusion patterns.
65-
updateRepos() {
53+
# Ensure the ignores are up-to-date
6654
if [[ ! -e "$dcs/ignore.global" ]]; then
6755
echo "/.dcs.d/git.*" >"$dcs/ignore.global"
6856
gitg add "$dcs/ignore.global"
@@ -74,18 +62,48 @@ updateRepos() {
7462
touch "$dcs/ignore.local"
7563
gitl add "$dcs/ignore.local"
7664
fi
77-
while IFS= read -rd '' localfile; do
65+
while IFS= read -u3 -rd '' localfile; do
7866
# FIXME: Handle filenames with * ? and newlines in them.
7967
printf '/%s\n' "$localfile"
80-
done < <(gitl ls-files --full-name -z "$workdir") >>"$dcs/git.global/info/exclude"
81-
}; updateRepos
68+
done 3< <(gitl ls-files --full-name -z "$workdir") >>"$dcs/git.global/info/exclude"
69+
}
70+
71+
72+
# Initialize our working directory.
73+
workdir=$(
74+
default=$PWD
75+
until [[ -e .dcs.d || $PWD = / ]]; do cd ..; done
76+
[[ -e .dcs.d ]] && echo "$PWD" || echo "$default"
77+
)
78+
dcs=$workdir/.dcs.d
79+
branch_global=global/master
80+
branch_local=local/${HOSTNAME%%.*}
8281

8382

8483
# Run dcs action.
8584
action=${1:-status}; shift
8685
case $action in
86+
init)
87+
workdir=$PWD
88+
dcs=$workdir/.dcs.d
89+
if [[ ! -e "$dcs" ]]; then
90+
[[ $(ask -c Ny 'Initialize DCS in %s?' "$workdir") = y ]] || exit
91+
mkdir -p "$dcs"
92+
fi
93+
if [[ ! -e "$dcs/git.global" ]]; then
94+
command git init --bare "$dcs/git.global"
95+
echo "ref: refs/heads/$branch_global" > "$dcs/git.global/HEAD"
96+
fi
97+
if [[ ! -e "$dcs/git.local" ]]; then
98+
command git init --bare "$dcs/git.local"
99+
echo "ref: refs/heads/$branch_local" > "$dcs/git.local/HEAD"
100+
fi
101+
updateRepos
102+
103+
;;
87104
st|status)
88105
[[ $1 = -a ]] && all=1 && shift
106+
updateRepos
89107

90108
inf '%s:' "$branch_global"
91109
if (( all )); then
@@ -102,26 +120,61 @@ case $action in
102120
fi
103121
;;
104122

123+
s|stage)
124+
stageFiles() {
125+
inf 'Interactively staging:'
126+
gitg ls-files --exclude-standard --directory --no-empty-directory -o "$@"
127+
128+
while IFS= read -u3 -rd ''; do
129+
while true; do
130+
read size _ < <(du -xsh "$REPLY")
131+
count=$(gitg ls-files --exclude-standard --directory --no-empty-directory -o "$REPLY" | wc -l)
132+
(( count == 1 )) && countSuffix= || countSuffix=s
133+
stageAction=$(ask -c gliSec '%s [%s, %d %s] - stage %slobal, %socal, %sgnore, %skip, %snter, show %sontents?' \
134+
"$REPLY" "$size" "$count" "file$countSuffix" g l i s e c)
135+
case $stageAction in
136+
g) gitg add "$REPLY" && break ;;
137+
l) gitl add "$REPLY" && break ;;
138+
i) gitg ls-files --full-name --directory -o -z "$REPLY" >> "$dcs/ignore.global" && break ;;
139+
S) break ;;
140+
e) [[ -d "$REPLY" ]] && stageFiles "$REPLY" && break ;;
141+
c) if [[ -d "$REPLY" ]]; then
142+
gitg ls-files -o "$REPLY" | "${PAGER:-less}"
143+
else
144+
"${PAGER:-less}" "$REPLY"
145+
fi ;;
146+
esac
147+
done
148+
done 3< <(gitg ls-files --exclude-standard --directory --no-empty-directory -o -z "$@")
149+
}
150+
151+
updateRepos
152+
stageFiles "$@"
153+
;;
154+
105155
u|unstage)
106-
while IFS= read -rd ''; do
156+
updateRepos
157+
158+
while IFS= read -u3 -rd ''; do
107159
gitg rm --cached "$REPLY"
108-
done < <(gitg ls-files -z "$@")
109-
while IFS= read -rd ''; do
160+
done 3< <(gitg ls-files -z "$@")
161+
while IFS= read -u3 -rd ''; do
110162
gitl rm --cached "$REPLY"
111-
done < <(gitl ls-files -z "$@")
163+
done 3< <(gitl ls-files -z "$@")
112164
;;
113165

114166
g|global|l|local|G|globalize|L|localize)
167+
updateRepos
115168
repo_global
116169
[[ $action = [lL]* ]] && repo_local
117170
[[ $action = [GL] || $action = *ize ]] && move=1 || move=0
118171

119172
files=()
120-
while IFS= read -rd ''; do
173+
while IFS= read -u3 -rd ''; do
121174
if (( move )) || ! ogithas "$REPLY"; then
122175
files+=( "$REPLY" )
123176
fi
124-
done < <(
177+
done 3< <(
125178
if (( move )); then
126179
ogit ls-files --exclude-standard -z "$@"
127180
else
@@ -144,6 +197,8 @@ case $action in
144197
;;
145198

146199
d|down|pull)
200+
updateRepos
201+
147202
if [[ $(gitg remote show) = origin ]]; then
148203
inf 'Pulling %s...' "$branch_global"
149204
gitg pull origin "$branch_global"
@@ -155,6 +210,7 @@ case $action in
155210
;;
156211

157212
u|up|push)
213+
updateRepos
158214
gitg commit -m "dcs global commit"
159215
gitl commit -m "dcs local commit" --untracked-files=no
160216

@@ -169,6 +225,7 @@ case $action in
169225
;;
170226

171227
r|remote)
228+
updateRepos
172229
if [[ $1 = -l ]]; then
173230
repo_local
174231
shift

0 commit comments

Comments
 (0)