blob: 98769f6b3259834eda95a041eca75e9bc74c46f5 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002
3# Copyright (c) 2012 Wind River Systems, 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 version 2 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12# See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18import os
19import sys
20import optparse
21import re
22import subprocess
23import shutil
24
25pkg_cur_dirs = {}
26obsolete_dirs = []
27parser = None
28
29def err_quit(msg):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060030 print(msg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031 parser.print_usage()
32 sys.exit(1)
33
34def parse_version(verstr):
35 elems = verstr.split(':')
36 epoch = elems[0]
37 if len(epoch) == 0:
38 return elems[1]
39 else:
40 return epoch + '_' + elems[1]
41
42def run_command(cmd):
43 pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
44 output = pipe.communicate()[0]
45 if pipe.returncode != 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060046 print("Execute command '%s' failed." % cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047 sys.exit(1)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060048 return output.decode('utf-8')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049
50def get_cur_arch_dirs(workdir, arch_dirs):
51 pattern = workdir + '/(.*?)/'
52
Patrick Williamsc0f7c042017-02-23 20:41:17 -060053 cmd = "bitbake -e | grep ^SDK_SYS="
Patrick Williamsc124f4f2015-09-15 14:41:29 -050054 output = run_command(cmd)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060055 sdk_sys = output.split('"')[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056
57 # select thest 5 packages to get the dirs of current arch
Patrick Williamsc0f7c042017-02-23 20:41:17 -060058 pkgs = ['hicolor-icon-theme', 'base-files', 'acl-native', 'binutils-crosssdk-' + sdk_sys, 'nativesdk-autoconf']
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059
60 for pkg in pkgs:
61 cmd = "bitbake -e " + pkg + " | grep ^IMAGE_ROOTFS="
62 output = run_command(cmd)
63 output = output.split('"')[1]
64 m = re.match(pattern, output)
65 arch_dirs.append(m.group(1))
66
67def main():
68 global parser
69 parser = optparse.OptionParser(
70 usage = """%prog
71
72%prog removes the obsolete packages' build directories in WORKDIR.
73This script must be ran under BUILDDIR after source file \"oe-init-build-env\".
74
75Any file or directory under WORKDIR which is not created by Yocto
76will be deleted. Be CAUTIOUS.""")
77
78 options, args = parser.parse_args(sys.argv)
79
80 builddir = run_command('echo $BUILDDIR').strip()
81 if len(builddir) == 0:
82 err_quit("Please source file \"oe-init-build-env\" first.\n")
83
84 if os.getcwd() != builddir:
85 err_quit("Please run %s under: %s\n" % (os.path.basename(args[0]), builddir))
86
Patrick Williamsc0f7c042017-02-23 20:41:17 -060087 print('Updating bitbake caches...')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088 cmd = "bitbake -s"
89 output = run_command(cmd)
90
91 output = output.split('\n')
92 index = 0
93 while len(output[index]) > 0:
94 index += 1
95 alllines = output[index+1:]
96
97 for line in alllines:
98 # empty again means end of the versions output
99 if len(line) == 0:
100 break
101 line = line.strip()
102 line = re.sub('\s+', ' ', line)
103 elems = line.split(' ')
104 if len(elems) == 2:
105 version = parse_version(elems[1])
106 else:
107 version = parse_version(elems[2])
108 pkg_cur_dirs[elems[0]] = version
109
110 cmd = "bitbake -e"
111 output = run_command(cmd)
112
113 tmpdir = None
114 image_rootfs = None
115 output = output.split('\n')
116 for line in output:
117 if tmpdir and image_rootfs:
118 break
119
120 if not tmpdir:
121 m = re.match('TMPDIR="(.*)"', line)
122 if m:
123 tmpdir = m.group(1)
124
125 if not image_rootfs:
126 m = re.match('IMAGE_ROOTFS="(.*)"', line)
127 if m:
128 image_rootfs = m.group(1)
129
130 # won't fail just in case
131 if not tmpdir or not image_rootfs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600132 print("Can't get TMPDIR or IMAGE_ROOTFS.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 return 1
134
135 pattern = tmpdir + '/(.*?)/(.*?)/'
136 m = re.match(pattern, image_rootfs)
137 if not m:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600138 print("Can't get WORKDIR.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139 return 1
140
141 workdir = os.path.join(tmpdir, m.group(1))
142
143 # we only deal the dirs of current arch, total numbers of dirs are 6
144 cur_arch_dirs = [m.group(2)]
145 get_cur_arch_dirs(workdir, cur_arch_dirs)
146
147 for workroot, dirs, files in os.walk(workdir):
148 # For the files, they should NOT exist in WORKDIR. Remove them.
149 for f in files:
150 obsolete_dirs.append(os.path.join(workroot, f))
151
152 for d in dirs:
153 if d not in cur_arch_dirs:
154 continue
155
156 for pkgroot, pkgdirs, filenames in os.walk(os.path.join(workroot, d)):
157 for f in filenames:
158 obsolete_dirs.append(os.path.join(pkgroot, f))
159
160 for pkgdir in sorted(pkgdirs):
161 if pkgdir not in pkg_cur_dirs:
162 obsolete_dirs.append(os.path.join(pkgroot, pkgdir))
163 else:
164 for verroot, verdirs, verfiles in os.walk(os.path.join(pkgroot, pkgdir)):
165 for f in verfiles:
166 obsolete_dirs.append(os.path.join(pkgroot, f))
167 for v in sorted(verdirs):
168 if v not in pkg_cur_dirs[pkgdir]:
169 obsolete_dirs.append(os.path.join(pkgroot, pkgdir, v))
170 break
171
172 # just process the top dir of every package under tmp/work/*/,
173 # then jump out of the above os.walk()
174 break
175
176 # it is convenient to use os.walk() to get dirs and files at same time
177 # both of them have been dealed in the loop, so jump out
178 break
179
180 for d in obsolete_dirs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600181 print("Deleting %s" % d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500182 shutil.rmtree(d, True)
183
184 if len(obsolete_dirs):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600185 print('\nTotal %d items.' % len(obsolete_dirs))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600187 print('\nNo obsolete directory found under %s.' % workdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500188
189 return 0
190
191if __name__ == '__main__':
192 try:
193 ret = main()
194 except Exception:
195 ret = 2
196 import traceback
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500197 traceback.print_exc()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500198 sys.exit(ret)