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 " add Stage changes or start tracking changes to FILE"
63 echo " clone Clone and track a remote file"
64 echo " import Import RCS history for FILE"
65 echo " init Synonym for track"
66 echo " list Synonym for tracked"
67 echo " track Start tracking changes to FILE"
68 echo " tracked List tracked files in current directory"
69 echo " view Browse FILE's history with gitk or tig"
70 echo " with Run a command in FILE's context"
72 echo "See 'zit help git' or 'git help' for git commands."
75 echo "usage: zig FILE"
76 echo "Browse FILE's history with tig."
79 echo "usage: zik FILE"
80 echo "Browse FILE's history with gitk."
89 test "$ZIT_FILE" || abort "Please specify a file"
90 test -f "$ZIT_FILE" || abort "No such file $ZIT_FILE"
91 test "$ZIT_FILE" = $(basename "$ZIT_FILE") || abort "Sorry, Zit only works on files in the current directory"
93 export GIT_WORK_TREE=$(pwd)
95 # first, check if a repo exists already, looking for
96 # .zit/file.git or .file.git, in that order
97 # if neither is found, and .zit exists, set the repo dir
98 # to .zit/file.git, otherwise set it to .file.git
99 GIT_DIR="$ZIT_DIR/$ZIT_FILE.git"
100 if ! test -d "$GIT_DIR"; then
101 GIT_DIR=".$ZIT_FILE.git"
102 if ! test -d "$GIT_DIR"; then
103 test -d "$ZIT_DIR" && GIT_DIR="$ZIT_DIR/$ZIT_FILE.git"
109 # initialize the zitdir, without actually making the first commit
112 test -e "$GIT_DIR" && abort "$GIT_DIR exists, is $ZIT_FILE tracked already?"
113 mkdir "$GIT_DIR" && echo "Initializing Zit repository in $GIT_DIR"
114 test -d "$GIT_DIR" || abort "Failed to create $GIT_DIR"
115 git init || abort "Failed to initialize Git repository in $GIT_DIR"
116 rm -rf "$GIT_DIR"/{hooks,info,branches,refs/tags,objects/pack,description}
117 if test -d "$ZIT_DIR"; then
118 ZIT_EXCLUDE="$ZIT_DIR/exclude"
120 ZIT_EXCLUDE="$GIT_DIR/exclude"
122 if ! test -f "$ZIT_EXCLUDE"; then
123 touch "$ZIT_EXCLUDE" || abort "Cannot create $ZIT_EXCLUDE file"
124 echo "# Ignore patterns used by Zit repositories in the parent worktree." > "$ZIT_EXCLUDE"
125 echo "# By default it's the single '*' glob, since we want to ignore all" >> "$ZIT_EXCLUDE"
126 echo "# non-tracked files in the work-tree." >> "$ZIT_EXCLUDE"
127 echo "# This file is autogenerated and there's usually no need to edit it." >> "$ZIT_EXCLUDE"
128 echo "*" >> "$ZIT_EXCLUDE"
130 git config core.excludesfile "$ZIT_EXCLUDE"
134 if test -f "$ZIT_DIR"; then
135 abort "$ZIT_DIR exists but it's not a directory, cannot continue"
140 if test -n "$1"; then
142 git add -f "$ZIT_FILE" || abort "Failed to add $ZIT_FILE"
143 git commit "$@" || abort "Failed to make first commit for $ZIT_FILE"
145 if test -d "$ZIT_DIR"; then
146 echo "$ZIT_DIR exists already"
155 # add the file if it is tracked, otherwise zit init
159 if test -d "$GIT_DIR"; then
167 export GIT_WORK_TREE="$(pwd)"
169 for file in "$ZIT_DIR"/*.git .*.git; do
170 if ! test -e $file; then
173 export GIT_DIR="$file"
177 (git ls-files -m -d -t; git ls-files -t) | uniq -f 1
179 # if $GIT_DIR is empty, no files were found
180 test "$GIT_DIR" || echo "(no files tracked by zit)"
183 # import an RCS-tracked file using rcs-fast-export, if found
185 which rcs-fast-export || abort "rcs-fast-export not found, I can't import RCS-tracked files, sorry"
187 # git-fast-import creates a pack file, so (re)build the objects/pack dir
188 mkdir -p "$GIT_DIR/objects/pack"
189 rcs-fast-export "$1" | git-fast-import
190 # for some reason, rcs-fast-export | git-fast-import leaves the original
191 # file in 'deleted' state, a situation which is easily fixed by adding
198 test -n "$SRC" || abort "Where do you want to clone from?"
202 ZIT_FILE=$(basename "$SRC" .git)
204 test -e "$ZIT_FILE" && abort "File $ZIT_FILE exists already"
205 test "$ZIT_FILE" = $(basename $ZIT_FILE) || abort "Sorry, Zit only works on files in the current directory"
206 touch "$ZIT_FILE" # to make zit_setup happy
207 zitdir_init "$ZIT_FILE"
209 git remote add origin "$SRC"
212 git checkout -b master origin/master
220 echo "zit version $VERSION"
244 if test -n "$DISPLAY" -a -n "$(which gitk)" ; then
246 elif test -n "$(which tig)" ; then
249 abort "Neither gitk or tig could be launched"
267 # Most commands will work with the generic catch-all mechanism used
268 # below, but some of them require a more thorough analysis of the
269 # parameters to decide whether $ZIT_FILE should be put back into the
270 # parameter list or not. For example,
271 # $ zit commit somefile
272 # wouldn't do what one expects it to do, unless 'add' is run first, however
273 # $ zit commit somefile -a
274 # would work correctly. So we handle some commands separately (for the
275 # moment just commit)
279 git commit "$@" "$ZIT_FILE"
281 # the raw<command> method can be used to not replicate $ZIT_FILE in the