sstate-cache-management.sh 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #!/bin/bash
  2. # Copyright (c) 2012 Wind River Systems, Inc.
  3. #
  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.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. # See the GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the Free Software
  15. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. #
  17. # Global vars
  18. cache_dir=
  19. confirm=
  20. fsym=
  21. total_deleted=0
  22. verbose=
  23. debug=0
  24. usage () {
  25. cat << EOF
  26. Welcome to sstate cache management utilities.
  27. sstate-cache-management.sh <OPTION>
  28. Options:
  29. -h, --help
  30. Display this help and exit.
  31. --cache-dir=<sstate cache dir>
  32. Specify sstate cache directory, will use the environment
  33. variable SSTATE_CACHE_DIR if it is not specified.
  34. --extra-layer=<layer1>,<layer2>...<layern>
  35. Specify the layer which will be used for searching the archs,
  36. it will search the meta and meta-* layers in the top dir by
  37. default, and will search meta, meta-*, <layer1>, <layer2>,
  38. ...<layern> when specified. Use "," as the separator.
  39. This is useless for --stamps-dir.
  40. -d, --remove-duplicated
  41. Remove the duplicated sstate cache files of one package, only
  42. the newest one will be kept.
  43. Conflicts with --stamps-dir.
  44. --stamps-dir=<dir1>,<dir2>...<dirn>
  45. Specify the build directory's stamps directories, the sstate
  46. cache file which IS USED by these build diretories will be KEPT,
  47. other sstate cache files in cache-dir will be removed. Use ","
  48. as the separator. For example:
  49. --stamps-dir=build1/tmp/stamps,build2/tmp/stamps
  50. Conflicts with --remove-duplicated.
  51. -L, --follow-symlink
  52. Rmove both the symbol link and the destination file, default: no.
  53. -y, --yes
  54. Automatic yes to prompts; assume "yes" as answer to all prompts
  55. and run non-interactively.
  56. -v, --verbose
  57. explain what is being done
  58. -d, --debug
  59. show debug info, repeat for more debug info
  60. EOF
  61. }
  62. if [ $# -lt 1 ]; then
  63. usage
  64. exit 0
  65. fi
  66. # Echo no files to remove
  67. no_files () {
  68. echo No files to remove
  69. }
  70. # Echo nothing to do
  71. do_nothing () {
  72. echo Nothing to do
  73. }
  74. # Read the input "y"
  75. read_confirm () {
  76. echo -n "$total_deleted files will be removed! "
  77. if [ "$confirm" != "y" ]; then
  78. echo -n "Do you want to continue (y/n)? "
  79. while read confirm; do
  80. [ "$confirm" = "Y" -o "$confirm" = "y" -o "$confirm" = "n" \
  81. -o "$confirm" = "N" ] && break
  82. echo -n "Invalid input \"$confirm\", please input 'y' or 'n': "
  83. done
  84. else
  85. echo
  86. fi
  87. }
  88. # Print error information and exit.
  89. echo_error () {
  90. echo "ERROR: $1" >&2
  91. exit 1
  92. }
  93. # Generate the remove list:
  94. #
  95. # * Add .done/.siginfo to the remove list
  96. # * Add destination of symlink to the remove list
  97. #
  98. # $1: output file, others: sstate cache file (.tgz)
  99. gen_rmlist (){
  100. local rmlist_file="$1"
  101. shift
  102. local files="$@"
  103. for i in $files; do
  104. echo $i >> $rmlist_file
  105. # Add the ".siginfo"
  106. if [ -e $i.siginfo ]; then
  107. echo $i.siginfo >> $rmlist_file
  108. fi
  109. # Add the destination of symlink
  110. if [ -L "$i" ]; then
  111. if [ "$fsym" = "y" ]; then
  112. dest="`readlink -e $i`"
  113. if [ -n "$dest" ]; then
  114. echo $dest >> $rmlist_file
  115. # Remove the .siginfo when .tgz is removed
  116. if [ -f "$dest.siginfo" ]; then
  117. echo $dest.siginfo >> $rmlist_file
  118. fi
  119. fi
  120. fi
  121. # Add the ".tgz.done" and ".siginfo.done" (may exist in the future)
  122. base_fn="${i##/*/}"
  123. t_fn="$base_fn.done"
  124. s_fn="$base_fn.siginfo.done"
  125. for d in $t_fn $s_fn; do
  126. if [ -f $cache_dir/$d ]; then
  127. echo $cache_dir/$d >> $rmlist_file
  128. fi
  129. done
  130. fi
  131. done
  132. }
  133. # Remove the duplicated cache files for the pkg, keep the newest one
  134. remove_duplicated () {
  135. local topdir
  136. local oe_core_dir
  137. local tunedirs
  138. local all_archs
  139. local all_machines
  140. local ava_archs
  141. local arch
  142. local file_names
  143. local sstate_list
  144. local fn_tmp
  145. local list_suffix=`mktemp` || exit 1
  146. # Find out the archs in all the layers
  147. echo -n "Figuring out the archs in the layers ... "
  148. oe_core_dir=$(dirname $(dirname $(readlink -e $0)))
  149. topdir=$(dirname $oe_core_dir)
  150. tunedirs="`find $topdir/meta* ${oe_core_dir}/meta* $layers -path '*/meta*/conf/machine/include' 2>/dev/null`"
  151. [ -n "$tunedirs" ] || echo_error "Can't find the tune directory"
  152. all_machines="`find $topdir/meta* ${oe_core_dir}/meta* $layers -path '*/meta*/conf/machine/*' -name '*.conf' 2>/dev/null | sed -e 's/.*\///' -e 's/.conf$//'`"
  153. all_archs=`grep -r -h "^AVAILTUNES .*=" $tunedirs | sed -e 's/.*=//' -e 's/\"//g'`
  154. # Add the qemu and native archs
  155. # Use the "_" to substitute "-", e.g., x86-64 to x86_64
  156. # Sort to remove the duplicated ones
  157. all_archs=$(echo $all_archs $all_machines $(uname -m) \
  158. | sed -e 's/-/_/g' -e 's/ /\n/g' | sort -u)
  159. echo "Done"
  160. sstate_suffixes="deploy-rpm deploy-ipk deploy-deb deploy package populate-lic populate-sysroot"
  161. # Save all the sstate files in a file
  162. sstate_list=`mktemp` || exit 1
  163. find $cache_dir -name 'sstate-*.tgz' >$sstate_list
  164. echo -n "Figuring out the archs in the sstate cache dir ... "
  165. for arch in $all_archs; do
  166. grep -q "\-$arch-" $sstate_list
  167. [ $? -eq 0 ] && ava_archs="$ava_archs $arch"
  168. done
  169. echo "Done"
  170. echo "The following archs have been found in the cache dir:"
  171. echo $ava_archs
  172. echo ""
  173. # Save the file list which needs to be removed
  174. local remove_listdir=`mktemp -d` || exit 1
  175. for suffix in $sstate_suffixes; do
  176. # Save the file list to a file, some suffix's file may not exist
  177. grep "sstate-.*_$suffix.tgz" $sstate_list >$list_suffix 2>/dev/null
  178. local deleted=0
  179. echo -n "Figuring out the sstate-xxx_$suffix.tgz ... "
  180. # There are at list 6 dashes (-) after arch, use this to avoid the
  181. # greedy match of sed.
  182. file_names=`for arch in $ava_archs; do
  183. sed -ne 's#.*/\(sstate-.*\)-'"$arch"'-.*-.*-.*-.*-.*-.*#\1#p' $list_suffix
  184. done | sort -u`
  185. fn_tmp=`mktemp` || exit 1
  186. rm_list="$remove_listdir/sstate-xxx_$suffix"
  187. for fn in $file_names; do
  188. [ -z "$verbose" ] || echo "Analyzing $fn-xxx_$suffix.tgz"
  189. for arch in $ava_archs; do
  190. grep -h "/$fn-$arch-" $list_suffix >$fn_tmp
  191. if [ -s $fn_tmp ] ; then
  192. [ $debug -gt 1 ] && echo "Available files for $fn-$arch- with suffix $suffix:" && cat $fn_tmp
  193. # Use the modification time
  194. to_del=$(ls -t $(cat $fn_tmp) | sed -n '1!p')
  195. [ $debug -gt 2 ] && echo "Considering to delete: $to_del"
  196. # The sstate file which is downloaded from the SSTATE_MIRROR is
  197. # put in SSTATE_DIR, and there is a symlink in SSTATE_DIR/??/ to
  198. # it, so filter it out from the remove list if it should not be
  199. # removed.
  200. to_keep=$(ls -t $(cat $fn_tmp) | sed -n '1p')
  201. [ $debug -gt 2 ] && echo "Considering to keep: $to_keep"
  202. for k in $to_keep; do
  203. if [ -L "$k" ]; then
  204. # The symlink's destination
  205. k_dest="`readlink -e $k`"
  206. # Maybe it is the one in cache_dir
  207. k_maybe="$cache_dir/${k##/*/}"
  208. # Remove it from the remove list if they are the same.
  209. if [ "$k_dest" = "$k_maybe" ]; then
  210. to_del="`echo $to_del | sed 's#'\"$k_maybe\"'##g'`"
  211. fi
  212. fi
  213. done
  214. rm -f $fn_tmp
  215. [ $debug -gt 2 ] && echo "Decided to delete: $to_del"
  216. gen_rmlist $rm_list "$to_del"
  217. fi
  218. done
  219. done
  220. [ ! -s "$rm_list" ] || deleted=`cat $rm_list | wc -l`
  221. [ -s "$rm_list" -a $debug -gt 0 ] && cat $rm_list
  222. echo "($deleted files will be removed)"
  223. let total_deleted=$total_deleted+$deleted
  224. done
  225. rm -f $list_suffix
  226. rm -f $sstate_list
  227. if [ $total_deleted -gt 0 ]; then
  228. read_confirm
  229. if [ "$confirm" = "y" -o "$confirm" = "Y" ]; then
  230. for list in `ls $remove_listdir/`; do
  231. echo -n "Removing $list.tgz (`cat $remove_listdir/$list | wc -w` files) ... "
  232. # Remove them one by one to avoid the argument list too long error
  233. for i in `cat $remove_listdir/$list`; do
  234. rm -f $verbose $i
  235. done
  236. echo "Done"
  237. done
  238. echo "$total_deleted files have been removed!"
  239. else
  240. do_nothing
  241. fi
  242. else
  243. no_files
  244. fi
  245. [ -d $remove_listdir ] && rm -fr $remove_listdir
  246. }
  247. # Remove the sstate file by stamps dir, the file not used by the stamps dir
  248. # will be removed.
  249. rm_by_stamps (){
  250. local cache_list=`mktemp` || exit 1
  251. local keep_list=`mktemp` || exit 1
  252. local rm_list=`mktemp` || exit 1
  253. local suffixes
  254. local sums
  255. local all_sums
  256. suffixes="populate_sysroot populate_lic package_write_ipk \
  257. package_write_rpm package_write_deb package deploy"
  258. # Figure out all the md5sums in the stamps dir.
  259. echo -n "Figuring out all the md5sums in stamps dir ... "
  260. for i in $suffixes; do
  261. # There is no "\.sigdata" but "_setcene" when it is mirrored
  262. # from the SSTATE_MIRRORS, use them to figure out the sum.
  263. sums=`find $stamps -maxdepth 2 -name "*.do_$i.*" \
  264. -o -name "*.do_${i}_setscene.*" | \
  265. sed -ne 's#.*_setscene\.##p' -e 's#.*\.sigdata\.##p' | \
  266. sed -e 's#\..*##' | sort -u`
  267. all_sums="$all_sums $sums"
  268. done
  269. echo "Done"
  270. # Save all the state file list to a file
  271. find $cache_dir -name 'sstate-*.tgz' | sort -u -o $cache_list
  272. echo -n "Figuring out the files which will be removed ... "
  273. for i in $all_sums; do
  274. grep ".*-${i}_.*" $cache_list >>$keep_list
  275. done
  276. echo "Done"
  277. if [ -s $keep_list ]; then
  278. sort -u $keep_list -o $keep_list
  279. to_del=`comm -1 -3 $keep_list $cache_list`
  280. gen_rmlist $rm_list "$to_del"
  281. let total_deleted=(`cat $rm_list | wc -w`)
  282. if [ $total_deleted -gt 0 ]; then
  283. [ $debug -gt 0 ] && cat $rm_list
  284. read_confirm
  285. if [ "$confirm" = "y" -o "$confirm" = "Y" ]; then
  286. echo "Removing sstate cache files ... ($total_deleted files)"
  287. # Remove them one by one to avoid the argument list too long error
  288. for i in `cat $rm_list`; do
  289. rm -f $verbose $i
  290. done
  291. echo "$total_deleted files have been removed"
  292. else
  293. do_nothing
  294. fi
  295. else
  296. no_files
  297. fi
  298. else
  299. echo_error "All files in cache dir will be removed! Abort!"
  300. fi
  301. rm -f $cache_list
  302. rm -f $keep_list
  303. rm -f $rm_list
  304. }
  305. # Parse arguments
  306. while [ -n "$1" ]; do
  307. case $1 in
  308. --cache-dir=*)
  309. cache_dir=`echo $1 | sed -e 's#^--cache-dir=##' | xargs readlink -e`
  310. [ -d "$cache_dir" ] || echo_error "Invalid argument to --cache-dir"
  311. shift
  312. ;;
  313. --remove-duplicated|-d)
  314. rm_duplicated="y"
  315. shift
  316. ;;
  317. --yes|-y)
  318. confirm="y"
  319. shift
  320. ;;
  321. --follow-symlink|-L)
  322. fsym="y"
  323. shift
  324. ;;
  325. --extra-layer=*)
  326. extra_layers=`echo $1 | sed -e 's#^--extra-layer=##' -e 's#,# #g'`
  327. [ -n "$extra_layers" ] || echo_error "Invalid extra layer $i"
  328. for i in $extra_layers; do
  329. l=`readlink -e $i`
  330. if [ -d "$l" ]; then
  331. layers="$layers $l"
  332. else
  333. echo_error "Can't find layer $i"
  334. fi
  335. done
  336. shift
  337. ;;
  338. --stamps-dir=*)
  339. stamps=`echo $1 | sed -e 's#^--stamps-dir=##' -e 's#,# #g'`
  340. [ -n "$stamps" ] || echo_error "Invalid stamps dir $i"
  341. for i in $stamps; do
  342. [ -d "$i" ] || echo_error "Invalid stamps dir $i"
  343. done
  344. shift
  345. ;;
  346. --verbose|-v)
  347. verbose="-v"
  348. shift
  349. ;;
  350. --debug)
  351. debug=`expr $debug + 1`
  352. echo "Debug level $debug"
  353. shift
  354. ;;
  355. --help|-h)
  356. usage
  357. exit 0
  358. ;;
  359. *)
  360. echo "Invalid arguments $*"
  361. echo_error "Try 'sstate-cache-management.sh -h' for more information."
  362. ;;
  363. esac
  364. done
  365. # sstate cache directory, use environment variable SSTATE_CACHE_DIR
  366. # if it was not specified, otherwise, error.
  367. [ -n "$cache_dir" ] || cache_dir=$SSTATE_CACHE_DIR
  368. [ -n "$cache_dir" ] || echo_error "No cache dir found!"
  369. [ -d "$cache_dir" ] || echo_error "Invalid cache directory \"$cache_dir\""
  370. [ -n "$rm_duplicated" -a -n "$stamps" ] && \
  371. echo_error "Can not use both --remove-duplicated and --stamps-dir"
  372. [ "$rm_duplicated" = "y" ] && remove_duplicated
  373. [ -n "$stamps" ] && rm_by_stamps
  374. [ -z "$rm_duplicated" -a -z "$stamps" ] && \
  375. echo "What do you want to do?"