33 from __future__ 
import print_function
 
   40 from distutils.spawn 
import find_executable
 
   53     Pretty print cmds, ask if they should be run, and if so, runs 
   56     :param cmds: a list of commands executed one after another, ``list`` 
   57     :param cwd: (optional) set cwd of command that is executed, ``str`` 
   58     :returns: ``True`` if cmds were run. 
   62         return '"%s"' % s 
if ' ' in s 
else s
 
   63     accepted = 
_ask(
'\n'.join([
' '.join([quote(s) 
for s 
in c]) 
for c 
in cmds]))
 
   71     ask user with provided comment. If user responds with y, return True 
   73     :param comment: comment, ``str`` 
   74     :return: ``True`` if user responds with y 
   76     sys.stdout.write(
'Okay to perform:\n\n%s\n(y/n)?\n' % comment)
 
   78         input = sys.stdin.readline().strip().lower()
 
   79         if input 
in [
'y', 
'n']:
 
   86     Runs cmds using subprocess.check_call. 
   88     :param cmds: a list of commands executed one after another, ``list`` 
   89     :param cwd: (optional) set cwd of command that is executed, ``str`` 
   93             subprocess.check_call(c, cwd=cwd)
 
   95             subprocess.check_call(c)
 
   99     print(
"""Usage: rosclean <command> 
  102 \trosclean check\tCheck usage of log files 
  103 \trosclean purge\tRemove log files 
  105     sys.exit(getattr(os, 
'EX_USAGE', 1))
 
  109     home_dir = rospkg.get_ros_home()
 
  110     log_dir = rospkg.get_log_dir()
 
  111     dirs = [(log_dir, 
'ROS node logs'),
 
  112             (os.path.join(home_dir, 
'rosmake'), 
'rosmake logs')]
 
  113     return [x 
for x 
in dirs 
if os.path.isdir(x[0])]
 
  118     for d, label 
in dirs:
 
  120         print(
'%s %s' % (desc, label))
 
  125     for dirpath, dirnames, filenames 
in os.walk(d):
 
  127             fp = os.path.join(dirpath, f)
 
  128             total_size += os.path.getsize(fp)
 
  134     Get human-readable disk usage for directory 
  136     :param d: directory path, ``str` 
  137     :returns: human-readable disk usage (du -h), ``str`` 
  140     if platform.system() 
in [
'Linux', 
'FreeBSD']:
 
  142             return subprocess.Popen([
'du', 
'-sh', d], stdout=subprocess.PIPE).communicate()[0].split()[0].decode()
 
  145     elif platform.system() == 
'Windows':
 
  147         return 'Total Size: ' + str(total_size) + 
' ' + d
 
  154     Get disk usage in bytes for directory 
  155     :param d: directory path, ``str`` 
  156     :returns: disk usage in bytes (du -b) or (du -A) * 1024, ``int`` 
  157     :raises: :exc:`CleanupException` If get_disk_usage() cannot be used on this platform 
  159     if platform.system() == 
'Windows':
 
  165     du = find_executable(
'du')
 
  167         if platform.system() == 
'Linux':
 
  169         elif platform.system() == 
'FreeBSD':
 
  170             cmd = [du, 
'-skA', d]
 
  174             if os.path.basename(os.readlink(du)) == 
'busybox':
 
  184         return int(subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].split()[0]) * unit
 
  191     Get files and directories in specified path sorted by last modified time 
  192     :param d: directory path, ```str``` 
  193     :return:  a list of files and directories sorted by last modified time (old first), ```list``` 
  195     files = os.listdir(d)
 
  196     files.sort(key=
lambda f: os.path.getmtime(os.path.join(d, f)))
 
  203     for d, label 
in dirs:
 
  205             print(
'Purging %s.' % label)
 
  206             if platform.system() == 
'Windows':
 
  207                 cmds = [[
'cmd', 
'/c', 
'rd', 
'/s', 
'/q', d]]
 
  209                 cmds = [[
'rm', 
'-rf', d]]
 
  214                     print(
'PLEASE BE CAREFUL TO VERIFY THE COMMAND BELOW!')
 
  217                 print(
'FAILED to execute command', file=sys.stderr)
 
  221             if log_size <= args.size * 1024 * 1024:
 
  222                 print(
'Directory size of %s is %d MB which is already below the requested threshold of %d MB.' % (label, log_size / 1024 / 1024, args.size))
 
  224             print(
'Purging %s until directory size is at most %d MB (currently %d MB).' % (label, args.size, log_size / 1024 / 1024))
 
  226                 print(
'PLEASE BE CAREFUL TO VERIFY THE COMMAND BELOW!')
 
  227                 if not _ask(
'Purge some of old logs in %s' % d):
 
  230                 if log_size <= args.size * 1024 * 1024:
 
  232                 path = os.path.join(d, f)
 
  234                 if platform.system() == 
'Windows':
 
  235                     cmds = [[
'cmd', 
'/c', 
'rd', 
'/s', 
'/q', path]]
 
  237                     cmds = [[
'rm', 
'-rf', path]]
 
  241                     print(
'FAILED to execute command', file=sys.stderr)
 
  247     parser = argparse.ArgumentParser(prog=
'rosclean')
 
  248     subparsers = parser.add_subparsers(required=
True, dest=
'{check,purge}')  
 
  249     parser_check = subparsers.add_parser(
'check', help=
'Check usage of log files')
 
  250     parser_check.set_defaults(func=_rosclean_cmd_check)
 
  251     parser_purge = subparsers.add_parser(
'purge', help=
'Remove log files')
 
  252     parser_purge.set_defaults(func=_rosclean_cmd_purge)
 
  253     parser_purge.add_argument(
'-y', action=
'store_true', default=
False, help=
'CAUTION: automatically confirms all questions to delete files')
 
  254     parser_purge.add_argument(
'--size', action=
'store', default=
None, type=int, help=
'Maximum total size in MB to keep when deleting old files')
 
  255     args = parser.parse_args(argv[1:])
 
  259 if __name__ == 
'__main__':