archives2git: --tag, --tagname, $TAGDEF, $TAG, $archname: new options and vars
[archives2git.git] / archives2git
blob78e3ce5f166343054f7ccd3955e2a3d53da719e6
1 #!/bin/sh
2 # Copyright © 2013,2014 Géraud Meyer <graud@gmx.com>
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 2 as
6 # published by the Free Software Foundation.
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 # for more details.
13 # You should have received a copy of the GNU General Public License along
14 # with this program. If not, see <http://www.gnu.org/licenses/>.
16 PROGRAM_NAME="archives2git"
17 PROGRAM_VERSION="0.1+"
18 help_message () {
19 cat <<HelpMessage
20 NAME
21 $PROGRAM_NAME - generate a Git history from a series of release tarballs
22 USAGE
23 $PROGRAM_NAME [<options>] [--] <archives_and_dirs>
24 OPTIONS
25 --repo <work_tree_subdir>
26 --rename <sh_code>
27 --keep-filter <sh_code>
28 --date <sh_code>
29 --title <sh_code>
30 --body <message>
31 --gitadd-arg <arg>
32 --gitci-arg <arg>
33 --gitfilter <nl_separated_args>
34 --tag
35 --tagname <sh_code>
36 --debug
37 --help
38 --version
39 SHELL VARIABLES
40 The following shell variables are usable if appropriate in the shell code
41 snippets passed as command line options: \$arch, \$archname, \$archdir,
42 \$file.
43 ENVIRONMENT
44 GIT_AUTHOR_NAME
45 GIT_AUTHOR_EMAIL
46 GIT_COMMITTER_NAME
47 GIT_COMMITTER_EMAIL
48 FILES
49 ~/.archives2gitrc
50 An example file is distributed.
51 EXAMPLES
52 See the README.
53 SEE ALSO
54 git-commit-tree(1), git_load_dirs(1)
55 HelpMessage
58 # default parameters
59 RENAME='echo "$file"' # $file $arch $archname
60 FILTER='false' # $file $arch $archname
61 DATE='' # $arch $archname
62 TITLE='echo "$arch"' # $arch $archname
63 BODY="" # message taken as is
64 ADDARGS=
65 CIARGS=
66 FILTERHEAD= # line separated arguments
67 TAG=
68 TAGDEF='printf version/; printf "%s\n" "$archname" |
69 LC_ALL=C sed -e '\''s/^.*[-_]\([0-9][-0-9.ab]*\)$/\1/'\'
70 # config (file, environment, command line)
71 [ -f "$HOME"/.archives2gitrc ] && . "$HOME"/.archives2gitrc
72 GIT_WORK_TREE=${GIT_WORK_TREE-.}
73 # may be a subdir of the top level
74 while [ $# -gt 0 ]
76 case $1 in
77 --repo)
78 shift; GIT_WORK_TREE=$1 ;;
79 --rename)
80 shift; RENAME=$1 ;;
81 --keep-filter)
82 shift; FILTER=$1 ;;
83 --date)
84 shift; DATE=$1 ;;
85 --title)
86 shift; TITLE=$1 ;;
87 --body)
88 shift; BODY=$1 ;;
89 --gitadd-arg)
90 shift; ADDARGS="$ADDARGS $1" ;;
91 --gitci-arg)
92 shift; CIARGS="$CIARGS $1" ;;
93 --gitfilter)
94 shift; FILTERHEAD=$1 ;;
95 --tag)
96 TAG=$TAGDEF ;;
97 --tagname)
98 shift; TAG=$1 ;;
99 --debug)
100 set -x ;;
101 --help|-h)
102 help_message
103 exit ;;
104 --version)
105 echo "$PROGRAM_NAME version $PROGRAM_VERSION"
106 exit ;;
107 --?*)
108 echo >&2 "$PROGRAM_NAME: error: unknown option $1"
109 exit 255 ;;
111 shift; break ;;
113 break ;;
114 esac
115 shift
116 done
117 # setup
118 NL='
120 TMPDIR=$(mktemp -d)
121 WRKDIR=$(pwd)
122 # git repository check
123 cd "$GIT_WORK_TREE" &&
124 { test -d .git || git rev-parse --git-dir >/dev/null; } ||
126 echo >&2 "$PROGRAM_NAME: error: not in a git repository ($(pwd))"
127 exit 255
129 test -z "$(git status --porcelain)" &&
130 git update-index -q --refresh ||
132 echo >&2 "$PROGRAM_NAME: error: unstaged files or dirty index"
133 exit 254
136 # main
137 set -e
138 OLDIFS=$IFS
139 for arch
141 # put the files in the archive dir
142 cd "$WRKDIR"
143 if [ -d "$arch" ]
144 then
145 cp -R "$arch" "$TMPDIR"
146 else
147 aunpack -X "$TMPDIR" "$arch"
149 archdir=$TMPDIR
150 archname=$( printf "%s\n" "$arch" | LC_ALL=C sed \
151 -e 's;^\([^/]*/\)*\([^/]\{1,\}\)/\{0,1\}$;\2;' \
152 -e 's;\.\([Zz]\|lzo\|bz\|gz\|bz2\|xz\|lzma\|7z\|lz\|rz\|lrz\)$;;' \
153 -e 's;\.\(tar\|t[Zz]\|tzo\|tbz\|tgz\|tbz2\|txz\|t7z\|tlz\|lha\|lzh\|7z\|alz\|arj\|zip\|rar\|jar\|war\|ace\|cab\|a\|cpio\|shar\|rpm\|deb\)$;;' \
154 -e 's;\.\(orig\)$;;' )
155 # remove (almost) everything from the repository dir
156 cd "$GIT_WORK_TREE"
157 for file in * .*
159 [ -e "$file" ] || continue
160 [ x"$file" = x"." ] || [ x"$file" = x".." ] || [ x"$file" = x".git" ] && continue
161 eval "$FILTER" || { git rm -r "$file" || rm -R "$file"; }
162 done
163 # move the content of the temp dir to the repository and stage it
164 for file in "$archdir"/* "$archdir"/.*
166 [ -e "$file" ] || continue
167 file=${file#$archdir/}
168 [ x"$file" = x"." ] || [ x"$file" = x".." ] && continue
169 name=$(eval "$RENAME")
170 if [ -n "$name" ]
171 then
172 [ ! -e ./"$name" ] || rm -R ./"$name"
173 # remove conflicting file (previously kept or renamed to the same name)
174 mv "$archdir"/"$file" ./"$name"
175 git add $ADDARGS ./"$name"
176 else
177 rm -R "$archdir"/"$file"
179 done
180 # commit, filter and clean up
181 file=
182 git commit -m "$(eval "$TITLE")${BODY:+$NL$BODY}" \
183 ${DATE:+--date "$(eval "$DATE")"} $CIARGS
184 if [ -n "$FILTERHEAD" ]
185 then
186 IFS=$NL
187 git filter-branch $FILTERHEAD -- HEAD^..HEAD
188 rm -R "$(git rev-parse --git-dir)"/refs/original/
189 IFS=$OLDIFS
191 if [ -n "$TAG" ]
192 then
193 tagmessage=$(eval "$TAG" | LC_ALL=C tail -n +2)
194 tagname=$(eval "$TAG" | LC_ALL=C head -1)
195 git tag ${tagmessage:+-m "$tagmessage"} "$tagname"
197 done
199 # cleanup
200 rmdir "$TMPDIR"