1#! /bin/sh 2# 3# Copyright (C) 2009-2010, 2014, 2018-2020 Free Software Foundation, Inc. 4# 5# This program is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation; either version 3 of the License, or 8# (at your option) any 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, see <https://www.gnu.org/licenses/>. 17# 18 19# Usage: convert-archive FROM TO [FROMFILE [TOFILE]] 20# where FROM is dir or dirgz or dirbz2 or dirxz or cvs or git 21# and TO is dir or dirgz or dirbz2 or dirxz or cvs or git 22# This will read FROMFILE (default: archive.$FROM.tar.gz) 23# and produce TOFILE (default: archive.$TO.tar.gz). 24 25progname=$0 26package=@PACKAGE@ 27version=@VERSION@ 28 29# func_usage 30# outputs to stdout the --help usage message. 31func_usage () 32{ 33 echo "\ 34Usage: convert-archive FROM TO [FROMFILE [TOFILE]] 35 36Converts the archive of gettext infrastructure from the FROM format 37to the TO format. 38FROMFILE is the original file, defaulting to archive.\$FROM.tar.gz. 39TOFILE is the destination file, defaulting to archive.\$TO.tar.gz. 40 41Report bugs in the bug tracker at <https://savannah.gnu.org/projects/gettext> 42or by email to <bug-gettext@gnu.org>." 43} 44 45# func_version 46# outputs to stdout the --version message. 47func_version () 48{ 49 echo "$progname (GNU $package) $version" 50 echo "Copyright (C) 2009-2020 Free Software Foundation, Inc. 51License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> 52This is free software: you are free to change and redistribute it. 53There is NO WARRANTY, to the extent permitted by law." 54 echo "Written by" "Bruno Haible" 55} 56 57# func_fatal_error message 58# outputs to stderr a fatal error message, and terminates the program. 59func_fatal_error () 60{ 61 echo "convert-archive: *** $1" 1>&2 62 echo "convert-archive: *** Stop." 1>&2 63 exit 1 64} 65 66# Command-line option processing. 67 68if { { test $# = 2 || test $# = 3 || test $# = 4; } \ 69 && case "$1" in dir | cvs | git ) true;; *) false;; esac \ 70 && case "$2" in dir | cvs | git ) true;; *) false;; esac; }; then 71 : 72else 73 echo "Usage: convert-archive {dir|cvs|git} {dir|cvs|git} [fromfile [tofile]]" 74 exit 1 75fi 76 77from="$1" 78to="$2" 79fromfile="$3" 80test -n "$fromfile" || fromfile=`pwd`/archive.$from.tar.gz 81tofile="$4" 82test -n "$tofile" || tofile=`pwd`/archive.$to.tar.gz 83 84unpacked=`pwd`/unpacked-files 85mkdir "$unpacked" || { 86 if test -d "$unpacked"; then 87 func_fatal_error "directory $unpacked already exists" 88 else 89 func_fatal_error "cannot create directory $unpacked" 90 fi 91} 92 93# Unpack the original archive. 94case "$from" in 95 dir*) 96 { case "$from" in 97 dir) cat < "$fromfile" ;; 98 dirgz) gzip -d -c < "$fromfile" ;; 99 dirbz2) bzip2 -d -c < "$fromfile" ;; 100 dirxz) xz -d -c < "$fromfile" ;; 101 esac 102 } \ 103 | (cd "$unpacked" && tar xf -) \ 104 || func_fatal_error "file copy failed" 105 ;; 106 107 cvs) 108 # Set variables 109 # - work_dir directory containing the temporary checkout 110 work_dir=tmpwrk$$ 111 mkdir "$work_dir" || { 112 if test -d "$work_dir"; then 113 func_fatal_error "directory $work_dir already exists" 114 else 115 func_fatal_error "cannot create directory $work_dir" 116 fi 117 } 118 119 # Set variables 120 # - cvs_dir directory containing the temporary repository 121 cvs_dir=tmpcvs$$ 122 # Use an umask of 077, to avoid attacks that work by overwriting files in 123 # the "$CVSROOT"/CVSROOT directory. 124 (umask 077 && mkdir "$cvs_dir") || { 125 if test -d "$cvs_dir"; then 126 func_fatal_error "directory $cvs_dir already exists" 127 else 128 func_fatal_error "cannot create directory $cvs_dir" 129 fi 130 } 131 CVSROOT=`pwd`/"$cvs_dir" 132 unset CVS_CLIENT_LOG 133 unset CVS_CLIENT_PORT 134 unset CVS_IGNORE_REMOTE_ROOT 135 unset CVS_LOCAL_BRANCH_NUM 136 unset CVS_NOBASES 137 unset CVS_PASSFILE 138 unset CVS_PASSWORD 139 unset CVS_PROXY_PORT 140 unset CVS_RCMD_PORT 141 unset CVS_RSH 142 unset CVS_SERVER 143 unset CVS_SERVER_SLEEP 144 CVS_SIGN_COMMITS= 145 export CVS_SIGN_COMMITS 146 unset CVS_SSH 147 unset CVS_VERIFY_CHECKOUTS 148 unset CVS_VERIFY_TEMPLATE 149 unset CVSIGNORE 150 unset CVSREAD 151 unset CVSREADONLYFS 152 unset CVSUMASK 153 unset CVSWRAPPERS 154 155 # Need to pass -d "$CVSROOT", because there may be a CVS directory in the 156 # current directory. 157 cvs -d "$CVSROOT" init || func_fatal_error "cvs init failed" 158 gzip -d -c < "$fromfile" | (cd "$cvs_dir" && tar xf -) 159 160 # A witness that contains all versions. 161 # Can be e.g. ABOUT-NLS, intl/ChangeLog, m4/gettext.m4. 162 witness='ABOUT-NLS' 163 164 # Get list of tags or versions. 165 sed_extract_tags_from_log1='/^symbolic names:/{ 166:a 167/^ /p 168n 169ba 170} 171/^keyword substitution:/q' 172 sed_extract_tags_from_log2='s/^ \([^:]*\):.*/\1/' 173 rlog_harmless_warning_regex="warning: Unknown phrases like \`commitid \.\.\.;' are present\." 174 tags=` 175 ( LC_ALL=C rlog "$cvs_dir"/archive/$witness,v 2>&1 1>&3 \ 176 | grep -v "$rlog_harmless_warning_regex" 1>&2 ) 3>&1 \ 177 | sed -n -e "$sed_extract_tags_from_log1" \ 178 | sed -e "$sed_extract_tags_from_log2"` 179 test -n "$tags" || func_fatal_error "no release tags found" 180 sed_tag_to_version='s/_/./g' 181 for tag in $tags; do 182 if test $tag != release; then 183 version=`echo "$tag" | sed -e "$sed_tag_to_version"` 184 (cd "$work_dir" 185 cvs -d "$CVSROOT" checkout -r"$tag" archive > /dev/null 2> cvs.err \ 186 || { cat cvs.err 1>&2; exit 1; } 187 cat cvs.err | grep -v '^cvs checkout: Updating' 188 find archive -name CVS -type d -print | xargs rm -rf 189 rm -rf CVS 190 ) || func_fatal_error "cvs checkout failed" 191 mv "$work_dir"/archive "$unpacked/$version" 192 fi 193 done 194 rm -rf "$cvs_dir" 195 rm -rf "$work_dir" 196 ;; 197 198 git) 199 # Set variables 200 # - work_dir directory containing the temporary checkout 201 work_dir=tmpwrk$$ 202 mkdir "$work_dir" || { 203 if test -d "$work_dir"; then 204 func_fatal_error "directory $work_dir already exists" 205 else 206 func_fatal_error "cannot create directory $work_dir" 207 fi 208 } 209 210 mkdir "$work_dir/master" || func_fatal_error "mkdir failed" 211 gzip -d -c < "$fromfile" | (cd "$work_dir/master" && tar xf -) 212 (unset GIT_CONFIG 213 unset XDG_CONFIG_HOME 214 unset HOME 215 GIT_CONFIG_NOSYSTEM=1; export GIT_CONFIG_NOSYSTEM 216 cd "$work_dir" 217 tags=`cd master && git tag` 218 test -n "$tags" || func_fatal_error "no release tags found" 219 for tag in $tags; do 220 if test $tag != empty; then 221 version=$tag 222 (cd master && git checkout -q $tag) \ 223 || func_fatal_error "git checkout failed" 224 rm -f master/.gitignore 225 mv master/.git .git 226 mkdir "$unpacked/$version" || func_fatal_error "mkdir failed" 227 (cd master && tar cf - .) | (cd "$unpacked/$version" && tar xf -) \ 228 || func_fatal_error "file copy failed" 229 mv .git master/.git 230 fi 231 done 232 ) 233 rm -rf "$work_dir" 234 ;; 235esac 236 237# Find a good 'tar' program. 238existing_file=gettext-0.10.35/ABOUT-NLS 239TAR=tar 240TAR_OPTIONS= 241for prog in tar gnutar gtar; do 242 if (cd "$unpacked" && $prog cf - --owner=root --group=root "$existing_file") >/dev/null 2>&1; then 243 TAR=$prog 244 TAR_OPTIONS='--owner=root --group=root' 245 break 246 fi 247done 248 249# Create the target archive. 250case "$to" in 251 dir*) 252 (cd "$unpacked" && $TAR cf - $TAR_OPTIONS *) \ 253 | { case "$to" in 254 dir) cat > "$tofile" ;; 255 dirgz) gzip -c -9 > "$tofile" ;; 256 dirbz2) bzip2 -c -9 > "$tofile" ;; 257 dirxz) xz -c -5 > "$tofile" ;; 258 esac 259 } \ 260 || func_fatal_error "archive creation failed" 261 ;; 262 263 cvs) 264 # Set variables 265 # - cvs_dir directory containing the temporary repository 266 cvs_dir=autopoint-files 267 # Use an umask of 077, to avoid attacks that work by overwriting files in 268 # the "$CVSROOT"/CVSROOT directory. 269 (umask 077 && mkdir "$cvs_dir") || { 270 if test -d "$cvs_dir"; then 271 func_fatal_error "directory $cvs_dir already exists" 272 else 273 func_fatal_error "cannot create directory $cvs_dir" 274 fi 275 } 276 CVSROOT=`pwd`/"$cvs_dir" 277 unset CVS_CLIENT_LOG 278 unset CVS_CLIENT_PORT 279 unset CVS_IGNORE_REMOTE_ROOT 280 unset CVS_PASSFILE 281 unset CVS_PASSWORD 282 unset CVS_RCMD_PORT 283 unset CVS_RSH 284 unset CVS_SERVER 285 unset CVS_SERVER_SLEEP 286 unset CVSIGNORE 287 unset CVSREAD 288 unset CVSUMASK 289 unset CVSWRAPPERS 290 291 # Set a nonstandard variable, for a good-looking cvs history. 292 cvsuser=bruno 293 gcc -shared -fPIC -O cvsuser.c -o cvsuser.so 294 cvsuser_hack=`pwd`/cvsuser.so 295 296 # Need to pass -d "$CVSROOT", because there may be a CVS directory in the 297 # current directory. 298 cvs -d "$CVSROOT" init || func_fatal_error "cvs init failed" 299 300 # Add the contents of the unpacked directory to the repository. 301 (cd "$unpacked" 302 for version in *; do 303 cvsver=`echo "$version" | sed -e 's/\./_/g'` 304 (cd $version 305 CVSUSER=$cvsuser LD_PRELOAD=$cvsuser_hack \ 306 cvs -d "$CVSROOT" import -m "Import $version" archive release "$cvsver" > /dev/null 307 ) || func_fatal_error "cvs import failed" 308 # In order to avoid keyword substitution, we have to use "cvs admin" 309 # in a temporary checkout. 310 mkdir tmpcheckout || func_fatal_error "mkdir failed" 311 (cd tmpcheckout \ 312 && cvs -d "$CVSROOT" checkout -r"$cvsver" archive > /dev/null \ 313 && cvs -d "$CVSROOT" admin -ko `find . -type f -print | sed -e 's,^\./,,' | grep -v '^CVS/' | grep -v '/CVS/'` > /dev/null 314 ) 2> cvs.err || { cat cvs.err 1>&2; func_fatal_error "cvs checkout or admin failed"; } 315 rm -rf tmpcheckout 316 done 317 ) 318 (cd "$cvs_dir" && $TAR cf - $TAR_OPTIONS archive) \ 319 | gzip -c -9 > "$tofile" \ 320 || func_fatal_error "archive creation failed" 321 rm -rf "$cvs_dir" cvsuser.so 322 ;; 323 324 git) 325 git_dir=`pwd`/tmpgit$$ 326 mkdir "$git_dir" || func_fatal_error "mkdir failed" 327 unset GIT_CONFIG 328 unset XDG_CONFIG_HOME 329 unset HOME 330 GIT_CONFIG_NOSYSTEM=1; export GIT_CONFIG_NOSYSTEM 331 (cd "$git_dir" && { 332 git init -q 333 git config user.name 'GNU Gettext Build' 334 git config user.email 'bug-gnu-gettext@gnu.org' 335 touch .gitignore 336 git add . 337 git commit --author="Bruno Haible <bruno@clisp.org>" \ 338 --message="Empty directory" 2>&1 >/dev/null 339 git tag empty 340 }) || func_fatal_error "git init failed" 341 sed_remove_leading_dot='s,^\./,,' 342 sed_remove_git_infrastructure='/^\.git/d' 343 (cd "$unpacked" 344 for version in *; do 345 (cd $version && tar cf - .) | \ 346 (cd "$git_dir" && { 347 prev_files=`find . -type f | sed -e "$sed_remove_leading_dot" -e "$sed_remove_git_infrastructure"` 348 if test -n "$prev_files"; then 349 git rm -q $prev_files 350 fi 351 tar xf - 352 git add . 353 git commit --author="Bruno Haible <bruno@clisp.org>" \ 354 --message="Import $version" 2>&1 >/dev/null 355 git tag "$version" 356 }) || func_fatal_error "file copy into git repository failed" 357 done 358 ) 359 (cd "$git_dir" && git reset -q --hard empty && git repack -a -d -q) \ 360 || func_fatal_error "git reset or repack failed" 361 (cd "$git_dir" && $TAR cf - $TAR_OPTIONS .git) \ 362 | gzip -c -9 > "$tofile" \ 363 || func_fatal_error "archive creation failed" 364 rm -rf "$git_dir" 365 ;; 366esac 367 368rm -rf "$unpacked" 369