3 # Zit: the git-based single-file content tracker
11 if test "$me" = zit ; then
18 USAGE="usage: zit COMMAND FILE [ARGS...]"
29 echo "usage: zit list"
30 echo "Show tracked files, with a one-letter prefix indicating their status:"
33 echo " R removed/deleted"
34 echo " C modified/changed"
35 echo " K to be killed"
39 echo "usage: zit import FILE"
40 echo "Import history from an RCS-tracked file. Requires rcs-fast-export."
43 echo "usage: zit view FILE"
44 echo "Browse FILE's history with gitk (if possible) or tig."
47 echo "usage: zit with FILE COMMAND..."
48 echo "Run COMMAND after setting up the git environment for FILE."
51 echo "usage: zit clone REPO [FILE]"
52 echo "Create and track FILE, retrieving its history from repository REPO."
53 echo "FILE is guessed by REPO by stripping the '.git' suffix from the last path component"
58 echo "Set up a git repository under .FILE.git to track changes for FILE."
59 echo "File must be a regular file and in the current directory."
62 echo " clone Clone and track a remote file"
63 echo " import Import RCS history for FILE"
64 echo " init Synonym for track"
65 echo " list Synonym for tracked"
66 echo " track Start tracking changes to FILE"
67 echo " tracked List tracked files in current directory"
68 echo " view Browse FILE's history with gitk or tig"
69 echo " with Run a command in FILE's context"
71 echo "See 'zit help git' or 'git help' for git commands."
74 echo "usage: zig FILE"
75 echo "Browse FILE's history with tig."
78 echo "usage: zik FILE"
79 echo "Browse FILE's history with gitk."
88 test "$ZIT_FILE" || abort "Please specify a file"
89 test -f "$ZIT_FILE" || abort "No such file $ZIT_FILE"
90 test "$ZIT_FILE" = $(basename "$ZIT_FILE") || abort "Sorry, Zit only works on files in the current directory"
92 export GIT_WORK_TREE=$(pwd)
94 # first, check if a repo exists already, looking for
95 # .zit/file.git or .file.git, in that order
96 # if neither is found, and .zit exists, set the repo dir
97 # to .zit/file.git, otherwise set it to .file.git
98 GIT_DIR="$ZIT_DIR/$ZIT_FILE.git"
99 if ! test -d "$GIT_DIR"; then
100 GIT_DIR=".$ZIT_FILE.git"
101 if ! test -d "$GIT_DIR"; then
102 test -d "$ZIT_DIR" && GIT_DIR="$ZIT_DIR/$ZIT_FILE.git"
108 # initialize the zitdir, without actually making the first commit
111 test -e "$GIT_DIR" && abort "$GIT_DIR exists, is $ZIT_FILE tracked already?"
112 mkdir "$GIT_DIR" && echo "Initializing Zit repository in $GIT_DIR"
113 test -d "$GIT_DIR" || abort "Failed to create $GIT_DIR"
114 git init || abort "Failed to initialize Git repository in $GIT_DIR"
115 rm -rf "$GIT_DIR"/{hooks,info,branches,refs/tags,objects/pack,description}
116 if test -d "$ZIT_DIR"; then
117 ZIT_EXCLUDE="$ZIT_DIR/exclude"
119 ZIT_EXCLUDE="$GIT_DIR/exclude"
121 if ! test -f "$ZIT_EXCLUDE"; then
122 touch "$ZIT_EXCLUDE" || abort "Cannot create $ZIT_EXCLUDE file"
123 echo "# Ignore patterns used by Zit repositories in the parent worktree." > "$ZIT_EXCLUDE"
124 echo "# By default it's the single '*' glob, since we want to ignore all" >> "$ZIT_EXCLUDE"
125 echo "# non-tracked files in the work-tree." >> "$ZIT_EXCLUDE"
126 echo "# This file is autogenerated and there's usually no need to edit it." >> "$ZIT_EXCLUDE"
127 echo "*" >> "$ZIT_EXCLUDE"
129 git config core.excludesfile "$ZIT_EXCLUDE"
135 git add -f "$ZIT_FILE" || abort "Failed to add $ZIT_FILE"
136 git commit "$@" || abort "Failed to make first commit for $ZIT_FILE"
138 if test -d "$ZIT_DIR"; then
139 echo "$ZIT_DIR exists already"
142 test -e "$ZIT_DIR" && abort "$ZIT_DIR exists but it's not a directory, cannot continue"
148 export GIT_WORK_TREE="$(pwd)"
150 for file in "$ZIT_DIR"/*.git .*.git; do
151 if ! test -e $file; then
154 export GIT_DIR="$file"
158 (git ls-files -m -d -t; git ls-files -t) | uniq -f 1
160 # if $GIT_DIR is empty, no files were found
161 test "$GIT_DIR" || echo "(no files tracked by zit)"
164 # import an RCS-tracked file using rcs-fast-export, if found
166 which rcs-fast-export || abort "rcs-fast-export not found, I can't import RCS-tracked files, sorry"
168 # git-fast-import creates a pack file, so (re)build the objects/pack dir
169 mkdir -p "$GIT_DIR/objects/pack"
170 rcs-fast-export "$1" | git-fast-import
171 # for some reason, rcs-fast-export | git-fast-import leaves the original
172 # file in 'deleted' state, a situation which is easily fixed by adding
179 test -n "$SRC" || abort "Where do you want to clone from?"
183 ZIT_FILE=$(basename "$SRC" .git)
185 test -e "$ZIT_FILE" && abort "File $ZIT_FILE exists already"
186 test "$ZIT_FILE" = $(basename $ZIT_FILE) || abort "Sorry, Zit only works on files in the current directory"
187 touch "$ZIT_FILE" # to make zit_setup happy
188 zitdir_init "$ZIT_FILE"
190 git remote add origin "$SRC"
193 git checkout -b master origin/master
201 echo "zit version $VERSION"
222 if test -n "$DISPLAY" -a -n "$(which gitk)" ; then
224 elif test -n "$(which tig)" ; then
227 abort "Neither gitk or tig could be launched"
245 # Most commands will work with the generic catch-all mechanism used
246 # below, but some of them require a more thorough analysis of the
247 # parameters to decide whether $ZIT_FILE should be put back into the
248 # parameter list or not. For example,
249 # $ zit commit somefile
250 # wouldn't do what one expects it to do, unless 'add' is run first,
253 # wouldn't work either), however
254 # $ zit commit somefile -a
255 # would work correctly. So we handle some commands separately (for the
256 # moment just add and commit)
260 git $cmd "$@" "$ZIT_FILE"
262 # the raw<command> method can be used to not replicate $ZIT_FILE in the