]> git.madduck.net Git - code/vcsh.git/blob - vcsh

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

6de5f56722277741a9caf8ade2a0e97806eb6c4d
[code/vcsh.git] / vcsh
1 #!/bin/sh
2
3 [ -n "$VCSH_DEBUG" ] && set -x
4
5 SELF=$(basename $0)
6
7 [ -z "$XDG_CONFIG_HOME" ] && XDG_CONFIG_HOME="$HOME/.config"
8 [ -z "$VCSH_BASE" ]       && VCSH_BASE="$XDG_CONFIG_HOME/vcsh/repo.d"
9 for check_directory in "$VCSH_BASE"
10 do
11         if [ ! -d "$check_directory" ]; then
12                 if [ -e "$check_directory" ]; then
13                         echo "$SELF: error: $check_directory exists but is not a directory" >&2
14                         exit 2
15                 else
16                         mkdir -p "$check_directory" || (echo "$SELF: error: could not create $check_directory" >&2; exit 2)
17                 fi
18         fi
19 done
20
21 debug() {
22         [ -n "$VCSH_DEBUG" ] && echo "$SELF: debug: $1"
23 }
24
25 verbose() {
26         if [ -n "$VCSH_DEBUG" ] || [ -n "$VCSH_VERBOSE" ]; then echo "$SELF: verbose: $1"; fi
27 }
28
29 #   use <repo>     Use this repository
30 #
31 #   exit              Exit vcsh mode" >&2
32 help() {
33         echo "usage: $SELF <args>
34
35    help              Display this help
36
37    list              List all repos
38
39    run <repo> \\
40        <command>     Use this repository
41
42    init <repo>       Initialize a new repository
43    clone <remote> \\
44          [<repo>]    Clone from an existing repository
45    seed-gitignore \\
46    <repo>            Seed .gitignore.d/<repo> from git ls-files" >&2
47 }
48
49 use() {
50         verbose "use() begin"
51         REPO_NAME="$1"
52         GIT_DIR="$VCSH_BASE/$REPO_NAME.git"
53
54         if [ ! -d "$GIT_DIR" ]; then
55                 echo E: no repository found for "$REPO_NAME" >&2
56                 return 2
57         fi
58
59         export GIT_DIR
60         export GIT_WORK_TREE="$(git config --get core.worktree)"
61         export VCSH_DIRECTORY="$REPO_NAME"
62         verbose "use() end"
63 }
64
65 init() {
66         verbose "init() begin"
67         [ -e "$GIT_DIR" ] &&
68                 echo "$SELF: fatal: $GIT_DIR exists" &&
69                 return 21
70         export GIT_WORK_TREE="$HOME"
71         mkdir -p "$GIT_WORK_TREE"
72         cd "$GIT_WORK_TREE" ||
73                 (echo "$SELF: fatal: could not enter $GIT_WORK_TREE" &&
74                  exit 20) || exit 20
75         cd "$GIT_WORK_TREE"
76         git init
77         git config core.worktree     "$GIT_WORK_TREE"
78         git config core.excludesfile ".gitignore.d/$REPO_NAME"
79         verbose "init() end"
80 }
81
82 leave() {
83         unset GIT_DIR
84         unset GIT_WORK_TREE
85         unset VCSH_DIRECTORY
86 }
87
88 if [ "$1" = 'help' ] || [ "$#" -eq 0 ]; then
89         help
90         [ "$1" = 'help' ]
91         exit $?
92
93 elif [ "$1" = 'list' ]; then
94         verbose "list begin"
95         for i in "$VCSH_BASE"/*.git; do
96                 echo $(basename "$i" .git)
97         done
98         verbose "list end"
99         exit 0
100
101 elif [ "$1" = 'run' ]; then
102         verbose "run begin"
103         use "$2"
104         shift 2
105         "$@"
106         leave
107         verbose "run end"
108         exit 0
109
110 #elif [ "$1" = 'use' ]; then
111 #       verbose "use begin"
112 #       if [ -n "$ZSH_VERSION" ]; then
113 #               if [ -o NO_IGNORE_EOF ]; then
114 #                       export VCSH_NO_IGNORE_EOF=1
115 #                       setopt IGNORE_EOF
116 #               fi
117 #               vcsh_exit() {
118 #                       vcsh exit;
119 #                       zle reset-prompt;
120 #               }
121 #               zle -N vcsh_exit
122 #               bindkey '^d' 'vcsh_exit'
123 #       fi
124 #       use $2
125 #       [ -n "$ZSH_VERSION" ] && [ "$USER" = richih ] && buildPS1
126 #       verbose "use end"
127 #       exit 0
128
129 elif [ "$1" = 'clone' ]; then
130         verbose "clone begin"
131         GIT_REMOTE="$2"
132         REPO_NAME="$3"
133         [ -z "$REPO_NAME" ] && REPO_NAME=$(basename "$GIT_REMOTE" .git)
134         export REPO_NAME
135         export GIT_DIR="$VCSH_BASE/$REPO_NAME.git"
136         init
137
138         git remote add origin "$GIT_REMOTE"
139         git config branch.master.remote origin
140         git config branch.master.merge  refs/heads/master
141         git config core.excludesfile    ".gitignore.d/$REPO_NAME"
142         git fetch
143         for object in $(git ls-tree -r origin/master | awk '{print $4}'); do
144                 [ -e "$object" ] &&
145                         echo "$SELF: error: $object exists." &&
146                         VCSH_CONFLICT=1;
147         done
148         [ "$VCSH_CONFLICT" = '1' ] &&
149                 echo "$SELF: fatal: will stop after fetching and not try to merge!\n" &&
150                 echo "  Once this situation has been resolved, run 'vcsh run <foo> git pull' to finish cloning.\n" &&
151                 exit 3
152         git merge origin/master
153 #       vcsh use $REPO_NAME
154         verbose "clone end"
155
156 elif [ "$1" = 'init' ]; then
157         verbose "init begin"
158         [ -z $2 ] && help && echo && echo "$SELF $1: please specify repository to work on" && return 0
159         export REPO_NAME="$2"
160         export GIT_DIR="$VCSH_BASE/$REPO_NAME.git"
161         init
162 #       vcsh use "$REPO_NAME"
163         verbose "init end"
164
165 #elif [ "$1" = 'exit' ]; then
166 #       verbose "exit begin"
167 #       if [ -n "$ZSH_VERSION" ] && [ "$VCSH_NO_IGNORE_EOF" = '1' ]; then
168 #               unset VCSH_NO_IGNORE_EOF
169 #               setopt NO_IGNORE_EOF
170 #       fi
171 #       leave
172 #       [ -n "$ZSH_VERSION" ] && [ "$USER" = richih ] && buildPS1
173 #       verbose "exit end"
174 #       exit 0
175
176 elif [ "$1" = 'seed-gitignore' ]; then
177         verbose "seed-gitignore begin"
178         [ -z $2 ] && help && echo && echo "$SELF $1: please specify repository to work on" && return 0
179         use "$2"
180         git config core.excludesfile ".gitignore.d/$REPO_NAME"
181         files=$(git ls-files)
182         gitignores=$(for file in $(git ls-files); do
183                 while true; do
184                         echo $file; new="${file%/*}"
185                         [ "$file" = "$new" ] && break
186                         file="$new"
187                 done;
188         done | sort -u | sed 's/^/!/')
189         [ -e .gitignore.d/$2 ] &&
190         echo "$SELF: .gitignore.d/$2 exists, moving it to .gitignore.d/$2.bak" &&
191         mv -f .gitignore.d/$2 .gitignore.d/$2.bak
192         echo '*' > .gitignore.d/$2
193         for gitignore in $gitignores; do
194                 echo $gitignore >> .gitignore.d/$2
195         done
196
197 else
198         verbose "defaulting to calling help()"
199         help
200         exit 3
201
202 fi
203