Add "locate" command to movein
[gregoa/movein.git] / movein
1 #!/bin/sh
2 #
3 # Copyright © 2008 Mike O'Connor <stew@vireo.org>
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2, or (at your option) any
8 # later version.
9
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 # USA.  
19
20
21 set -e
22
23 usage() {
24     bn=$(basename $0)
25     cat <<EOF
26 $0: manage home directory using mr
27
28 NAME
29   $bn - a command to manage detached git repositories using mr
30
31 SYNOPSIS
32   $bn command [options]
33
34   $bn init
35   $bn ls
36   $bn list
37   $bn ls-r
38   $bn list-remote
39   $bn add repository_name
40   $bn new repository_name file1 [file2 file3...]
41   $bn login repository_name
42   $bn exec repository_name command [arg1 arg2...]
43
44 COMMANDS
45   init 
46       create ~/.moveinrc, create/update  ~/.mrconfig
47
48   ls
49   list
50       show a list of local repositories
51
52   ls-r
53   list-remote
54       show a list of remote repositories
55
56   locate pattern
57       locate which repositories contain files matching pattern
58
59   add repository_name
60       checkout one or more repositories from the remote host and add it to
61       mr's configuration
62
63   new repository_name file1 [file2 file3...]  
64       create a new repository on the remote host, and checkin the
65       listed files to the new repository.   Add the new repository
66       to mr's configuration
67
68   login repository_name
69       start a subshell in repository_name
70
71   exec repository_name command [arg1 arg2...]
72       execute a command in the context of repository_name, for example:
73         $bn exec myrepo git status
74         $bn exec myrepo git ls-files
75
76 EOF
77
78     exit 1
79 }
80
81 [ $# -ge 1 ] || usage
82
83 GIT_HOST=git.vireo.org
84 REMOTE_REPOS=~/git
85 LOCAL_REPOS=~/.movein
86 MRCONFIG=~/.mrconfig
87 MOVEINRC=~/.moveinrc
88
89 [ -e "$MOVEINRC" ] && . "$MOVEINRC"
90
91 init() {
92
93     if [ $# -ne 0 ]; then 
94         usage
95     fi
96     
97     if [ -e $MOVEINRC ]; then
98         echo $MOVEINRC already exists
99         exit 1
100     fi
101
102     if ! which mr > /dev/null; then
103         echo '"mr" not found in the PATH'
104         exit 1
105     fi
106
107     echo -n "git server hostname? [git.vireo.org] " 
108     read GIT_HOST
109     if [ -z "$GIT_HOST" ]; then 
110         GIT_HOST=git.vireo.org
111     fi
112
113     echo -n "path to remote repositories? [~/git] " 
114     read REMOTE_REPOS
115     if [ -z "$REMOTE_REPOS" ]; then 
116         REMOTE_REPOS=~/git
117     fi
118
119     echo -n "Local repository directory? [~/.movein] " 
120     read LOCAL_REPOS
121     if [ -z "$LOCAL_REPOS" ]; then 
122         LOCAL_REPOS=~/.movein
123     fi
124
125     echo -n "Location of .mrconfig file? [~/.mrconfig] " 
126     read MRCONFIG
127     if [ -z "$MRCONFIG" ]; then 
128         MRCONFIG=~/.mrconfig
129     fi
130
131     cat <<EOF > $MOVEINRC
132 GIT_HOST=$GIT_HOST
133 REMOTE_REPOS=$REMOTE_REPOS
134 LOCAL_REPOS=$LOCAL_REPOS
135 MRCONFIG=$MRCONFIG
136 EOF
137
138     if [ ! -d "$LOCAL_REPOS" ]; then 
139         mkdir -p "$LOCAL_REPOS"
140     fi
141
142     mr -c "$MRCONFIG" config DEFAULT include="cat /usr/share/mr/git-fake-bare"
143     
144 }
145
146 login() {
147     if [ $# -ne 1 ]; then 
148         usage
149     fi
150
151     export GIT_DIR="$LOCAL_REPOS/${1}.git"
152     export GIT_WORK_TREE="$GIT_DIR/$(git config --get core.worktree)"
153
154     GIT_PS1_SHOWUNTRACKEDFILES= PSMOVEIN="movein:${1}" $SHELL -i || :
155 }
156
157 execin() {
158     local REPO
159     if [ $# -lt 1 ]; then
160         usage
161     fi
162
163     REPO=$1;shift
164
165     export GIT_DIR="$LOCAL_REPOS/${REPO}.git"
166     export GIT_WORK_TREE="$GIT_DIR/$(git config --get core.worktree)"
167
168     "$@"
169 }
170
171 add() {
172     if [ $# -lt 1 ]; then 
173         usage
174     fi
175
176     for REPO in "$@"; do
177       REPO_NAME=$REPO.git 
178       LOCAL_REPO=$LOCAL_REPOS/$REPO_NAME
179       REPO_URL=ssh://$GIT_HOST/$REMOTE_REPOS/$REPO_NAME
180       if [ -e "$LOCAL_REPO" ]; then
181           echo $LOCAL_REPO already exists
182           exit 1
183       else
184           trap "rm -rf $LOCAL_REPO" 0
185           mkdir "$LOCAL_REPO"
186           export GIT_DIR="$LOCAL_REPO"
187           git init --bare
188           git remote add origin $REPO_URL
189           git config branch.master.remote origin
190           git config branch.master.merge refs/heads/master
191           git config core.bare false
192           git config core.worktree ../../
193           git config status.showUntrackedFiles no
194           GIT_WORK_TREE="$LOCAL_REPO/../../" git pull
195           trap - 0
196
197           mr -c "$MRCONFIG" config "$LOCAL_REPO" checkout="git_fake_bare_checkout '$REPO_URL' 'REPO_NAME' '../../'"
198       fi
199     done
200 }
201
202 list() {
203     find "${LOCAL_REPOS}" -mindepth 1 -maxdepth 1 -type d | sed 's,^.*/\([^/]*\).git$,\1,'
204 }
205
206 listremote() {
207     ssh $GIT_HOST "
208         find '${REMOTE_REPOS}' -mindepth 1 -maxdepth 1 -type d | sed 's,^.*/\([^/]*\).git$,\1,'
209     " </dev/null
210 }
211
212 locate() {
213     local REPO
214     for REPO in $($0 list); do
215       (cd /; $0 exec "$REPO" git ls-files | sed -nr "/$1/{s/^/$REPO:/p}")
216     done
217 }
218
219 new() {
220     if [ $# -lt 2 ]; then 
221         usage
222     fi
223     REPO_NAME=$1.git ; shift
224     LOCAL_REPO="$LOCAL_REPOS/$REPO_NAME"
225     REPO_URL="ssh://$GIT_HOST/$REMOTE_REPOS/$REPO_NAME"
226
227     if [ ! -e "$1" ]; then
228         echo $1 not found
229         exit 1
230     fi
231
232     if [ -e "$LOCAL_REPO" ]; then
233         echo $LOCAL_REPO already exists
234         exit 1
235     else
236         trap "rm -rf $LOCAL_REPO" 0
237         mkdir -p "$LOCAL_REPO"
238
239         ssh $GIT_HOST "
240                GIT_DIR=$REMOTE_REPOS/$REPO_NAME git --bare init
241         " </dev/null
242
243         export GIT_DIR="$LOCAL_REPO"
244         git init --bare
245         git remote add origin $REPO_URL
246         git config branch.master.remote origin
247         git config branch.master.merge refs/heads/master
248         git config core.bare false
249         git config core.worktree ../../
250         git config status.showUntrackedFiles no
251         export GIT_WORK_TREE="$LOCAL_REPO/../../"
252         git add "$@"
253         git commit -m "initial checkin"
254         git push --all
255         
256         trap - 0
257
258         mr -c "$MRCONFIG" config "$LOCAL_REPO" checkout="git_fake_bare_checkout '$REPO_URL' 'REPO_NAME' '../../'"
259     fi
260
261 }
262
263
264 command=$1 ; shift
265 case "$command" in 
266     init)
267         init "$@"
268         ;;
269     add)
270         add "$@"
271         ;;
272     new)
273         new "$@"
274         ;;
275     login)
276         login "$@"
277         ;;
278     exec)
279         execin "$@"
280         ;;
281     ls)
282         list
283         ;;
284     list)
285         list
286         ;;
287     ls-r)
288         listremote
289         ;;
290     list-remote)
291         listremote
292         ;;
293     locate)
294         locate "$@"
295         ;;
296
297     *)
298         usage
299         exit 1
300         ;;
301 esac