Advertisement
justin_hanekom

apt-clone-clone.py

Apr 30th, 2019 (edited)
365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.28 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. from __future__ import (
  5.     absolute_import, division, print_function, unicode_literals
  6. )
  7. from nine import (
  8.     IS_PYTHON2, basestring, chr, class_types, filter, integer_types,
  9.     implements_iterator, implements_to_string, implements_repr,
  10.     input, iterkeys, iteritems, itervalues, long, map,
  11.     native_str, nine, nimport, range, range_list, reraise, str, zip
  12. )
  13.  
  14. argparse = nimport('argparse')
  15. glob = nimport('glob')
  16. grp = nimport('grp')
  17. os = nimport('os')
  18. pwd = nimport('pwd')
  19. subprocess = nimport('subprocess')
  20. sys = nimport('sys')
  21. time = nimport('time')
  22.  
  23. DEFAULT_PREFIX = 'home_'
  24.  
  25.  
  26. def run():
  27.     """Runs this program.
  28.  
  29.    The program runs 'apt-clone clone' to store the current package list
  30.    into a time-stamped file in the given destination directory.
  31.  
  32.    Returns:
  33.        None
  34.    """
  35.     start_time = time.time()
  36.     options = parse_cmd_line(default_prefix=DEFAULT_PREFIX)
  37.     remove_old_files(
  38.         pattern='{destdir}{sep}{prefix}*'.format(
  39.             destdir=options['destdir'],
  40.             sep=os.sep,
  41.             prefix=options['prefix']),
  42.         remove=options['remove'],
  43.         verbose=options['verbose'])
  44.     dest_prefix = generate_results_file_prefix(
  45.         dest_dir=options['destdir'],
  46.         prefix=options['prefix'])
  47.     apt_clone_clone(
  48.         dest_prefix=dest_prefix,
  49.         verbose=options['verbose'])
  50.     change_file_owner_group(
  51.         pattern='{}*apt-clone*'.format(dest_prefix),
  52.         user=options['user'],
  53.         group=options['user'],
  54.         verbose=options['verbose'])
  55.     if options['verbose']:
  56.         print('Done, in {} seconds!'.format(time.time() - start_time))
  57.  
  58.  
  59. def parse_cmd_line(default_prefix):
  60.     """Parses the command-line arguments.
  61.  
  62.    Arguments:
  63.        default_prefix: the default prefix for current package list
  64.  
  65.    Returns:
  66.        A dictionary with each of the supplied command-line arguments.
  67.    """
  68.     parser = argparse.ArgumentParser(
  69.         description="Stores apt-clone clone results")
  70.     parser.add_argument(
  71.         'user',
  72.         help=' '.join([
  73.             'specify the name of the owner of the apt-clone clone results file;',
  74.             'the results files user and group will be set to this value']))
  75.     parser.add_argument(
  76.         'destdir',
  77.         help=' '.join([
  78.             'specify the directory that the new results file',
  79.             'will be saved into']))
  80.     parser.add_argument(
  81.         '--prefix', '-p',
  82.         default=default_prefix,
  83.         help=' '.join([
  84.             'specify the prefix to use for the newly created results file',
  85.             "(default: '%(default)s')"]))
  86.     parser.add_argument(
  87.         '--remove', '-r',
  88.         action='store_true',
  89.         default=False,
  90.         help='specify this to have obsolete results files removed')
  91.     parser.add_argument(
  92.         '--verbose', '-v',
  93.         action='store_true',
  94.         default=False,
  95.         help='specify this to display verbose output')
  96.     # vars() turns Namespace into a regular dictionary
  97.     options = vars(parser.parse_args())
  98.     options['destdir'] = chomp_sep(options['destdir'])
  99.     return options
  100.  
  101.  
  102. def chomp_sep(dir_name):
  103.     """Removes any trailing directory separator characters from the given
  104.    directory name.
  105.  
  106.    Arguments:
  107.        dir_name: the name that has to have any trailing slashes removed
  108.  
  109.    Returns:
  110.        The directory name with no trailing separator characters
  111.    """
  112.     while dir_name.endswith(os.sep):
  113.         dir_name = dir_name[:-1]
  114.     return dir_name
  115.  
  116.  
  117. def generate_results_file_prefix(dest_dir, prefix):
  118.     """Generates a results file filename prefix.
  119.  
  120.    Arguments:
  121.        dest_dir: where the results file should be saved
  122.        prefix: the prefix to use for the results file
  123.  
  124.    Returns:
  125.        A results file filename prefix of the form:
  126.            <dest_dir>/<prefix><year><month><day><hour><minute><second>
  127.        where the year, month, day, etc. values represent the local time
  128.    """
  129.     localtime = time.localtime()
  130.     return ('{dest_dir}{sep}{prefix}{year:04d}{month:02d}{day:02d}' +
  131.         '{hour:02d}{minute:02d}{second:02d}').format(
  132.             dest_dir=dest_dir,
  133.             prefix=prefix,
  134.             year=localtime[0],
  135.             month=localtime[1],
  136.             day=localtime[2],
  137.             hour=localtime[3],
  138.             minute=localtime[4],
  139.             second=localtime[5],
  140.             sep=os.sep)
  141.  
  142.  
  143. def remove_old_files(**kwargs):
  144.     """Only keeps the newest files that match a glob pattern.
  145.  
  146.    Arguments:
  147.        kwargs: a dictionary with the following keys:-
  148.            'pattern'   - the glob pattern of files to remove
  149.            'remove'    - whether to remove old files
  150.            'verbose'   - whether to output text describing non-fatal events
  151.  
  152.    Returns:
  153.        None
  154.    """
  155.     pattern = kwargs.pop('pattern')
  156.     remove = kwargs.pop('remove')
  157.     verbose= kwargs.pop('verbose')
  158.     if kwargs:
  159.         raise TypeError('Unexpected **kwargs: %r' % kwargs)
  160.     if not remove:
  161.         return
  162.     for f in glob.glob(pattern):
  163.         os.remove(f)
  164.         if verbose:
  165.             print("Removed file '{filename}'".format(filename=f))
  166.  
  167.  
  168. def apt_clone_clone(dest_prefix, verbose):
  169.     """Creates a clone file
  170.  
  171.    Arguments:
  172.        dest_prefix:    the prefix to use for the apt-clone clone results file
  173.        verbose:        whether to output text describing non-fatal events
  174.  
  175.    Returns:
  176.        None
  177.   """
  178.     subprocess.call(
  179.         'apt-clone clone "{}" &>/dev/null'.format(dest_prefix),
  180.         shell=True)
  181.     if verbose:
  182.         print('Performed apt-clone clone to: {}'.format(dest_prefix))
  183.  
  184.  
  185. def change_file_owner_group(**kwargs):
  186.     """Changes the owner and group of the named file.
  187.  
  188.    Arguments:
  189.        kwargs: a dictionary with the following keys:-
  190.            'pattern':  the glob pattern of files to change ownership of
  191.            'user':     the new owner to assign to the file
  192.            'group':    the new group to assign to the file;
  193.                        this is the same as 'user' if not given
  194.            'verbose':  whether to output text describing non-fatal events
  195.  
  196.    Returns:
  197.        None
  198.    """
  199.     pattern = kwargs.pop('pattern')
  200.     user = kwargs.pop('user')
  201.     group = kwargs.pop('group', user)
  202.     verbose= kwargs.pop('verbose')
  203.     if kwargs:
  204.         raise TypeError('Unexpected **kwargs: %r' % kwargs)
  205.     for filename in glob.glob(pattern):
  206.         try:
  207.             os.chown(filename,
  208.                      pwd.getpwnam(user).pw_uid,
  209.                      grp.getgrnam(group).gr_gid)
  210.             if verbose:
  211.                 print(
  212.                     ' '.join(
  213.                         "Changed ownership of '{filename}'",
  214.                         "'{user}:{group}'".format(
  215.                             filename=filename,
  216.                             user=user,
  217.                             group=group)))
  218.         except os.OSError as err:
  219.             print("Unable to change ownership of "
  220.                 + "'{filename}' to '{user}:{group}' => {err}".format(
  221.                     filename=filename,
  222.                     user=user,
  223.                     group=group,
  224.                     err=err),
  225.                 file=sys.stderr)
  226.  
  227.  
  228. if __name__ == '__main__':
  229.     run()
  230.  
Tags: python
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement