예제 #1
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def restore(bu_dir, filelist=None, to_dir='.', verbose=False, keep=False, touch=False):
    def restore_file(file_nm):
        backup = os.path.join(bu_dir, file_nm)
        file_nm = file_nm if to_dir is None else os.path.relpath(os.path.join(to_dir, file_nm))
        _create_parents(file_nm)
        try:
            stat_data = os.stat(backup)
        except OSError as edata:
            output.perror(edata, backup)
            return False
        if stat_data.st_size == 0:
            try:
                os.unlink(file_nm)
            except OSError as edata:
                if edata.errno != errno.ENOENT:
                    output.perror(edata, file_nm)
                    return False
            if verbose:
                output.write('Removing %s\n' % file_nm)
            if not keep:
                os.unlink(backup)
                _remove_parents(backup)
        else:
            if verbose:
                output.write('Restoring %s\n' % file_nm)
            try:
                os.unlink(file_nm)
            except OSError as edata:
                if edata.errno != errno.ENOENT:
                    raise
            if not _link_or_copy_file(backup, stat_data, file_nm):
                return False
            if not keep:
                os.unlink(backup)
                _remove_parents(backup)
            if touch:
                os.utime(file_nm, None)
            else:
                os.utime(file_nm, (stat_data.st_mtime, stat_data.st_mtime))
        return True
    if not os.path.isdir(bu_dir):
        return False
    status = True
    if filelist is None or len(filelist) == 0:
        def onerror(exception):
            raise exception
        try:
            for basedir, dirnames, filenames in os.walk(bu_dir, onerror=onerror):
                reldir = '' if basedir == bu_dir else os.path.relpath(basedir, bu_dir)
                for filename in filenames:
                    if not restore_file(os.path.join(reldir, filename)):
                        return False
        except OSError as edata:
            output.perror(edata)
            return False
    else:
        for filename in filelist:
            if not restore_file(filename):
                return False
    return True
예제 #2
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def remove(bu_dir, filelist=False, verbose=False):
    '''Remove backup files'''
    def remove_file(backup):
        try:
            if verbose:
                output.write('Removing %s\n' % backup)
            os.unlink(backup)
        except OSError as edata:
            output.perror(edata, backup)
            return False
        try:
            _remove_parents(backup)
        except IOError as edata:
            output.perror(edata, backup)
            return False
        return True
    if not os.path.isdir(bu_dir):
        return False
    status = True
    if filelist is None or len(filelist) == 0:
        def onerror(exception):
            raise exception
        try:
            for basedir, dirnames, filenames in os.walk(bu_dir):
                for filename in filenames:
                    if not remove_file(os.path.join(basedir, filename)):
                        return False
        except IOError as edata:
            output.perror(edata)
            return False
    else:
        for filename in filelist:
            if not remove_file(os.path.join(bu_dir, filename)):
                return False
    return True
예제 #3
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def ensure_nolinks(filename):
    try:
        stat_data = os.stat(filename)
    except OSError as edata:
        output.perror(edata)
        return False
    if stat_data.st_nlink > 1:
        from_fd = to_fd = None
        try:
            from_fd = os.open(filename, os.O_RDONLY)
            # Temp file name is "path/to/.file.XXXXXX"
            to_fd, tmpname = tempfile.mkstemp(prefix=os.path.abspath(filename))
            _copy_fd(from_fd, to_fd)
            os.fchmod(to_fd, stat_data.st_mode)
            os.rename(tmpname, filename)
            return True;
        except OSError as edata:
            output.perror(edata)
            return False
        finally:
            if from_fd is not None:
                os.close(from_fd);
            if to_fd is not None:
                os.close(to_fd);
    else:
        return True
예제 #4
0
 def set_text(pfile, text):
     if args.opt_backup:
         try:
             shutil.copy2(pfile, pfile + '~')
         except Exception as edata:
             output.perror(edata)
     if args.opt_strip_trailing_whitespace:
         text = _trim_trailing_ws(text)
     putils.set_patch_hdr(pfile, text, omit_diffstat=args.opt_strip_diffstat)
예제 #5
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def _link_or_copy_file(from_fn, stat_data, to_fn):
    try:
        os.link(from_fn, to_fn)
    except OSError as edata:
        if edata.errno not in [errno.EXDEV, errno.EPERM, errno.EMLINK, errno.ENOSYS]:
            output.perror(edata, 'Could not link file \`%s\' to \`%s\'' % (from_fn, to_fn))
            return False
    else:
        return True
    return _copy_file(from_fn, stat_data, to_fn)
예제 #6
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def _copy_file(from_fn, stat_data, to_fn):
    is_ok = True;
    try:
        from_fd = os.open(from_fn, os.O_RDONLY)
    except OSError as edata:
        output.perror(edata)
        return False
    try:
        # make sure we don't inherit this file's mode.
        os.unlink(to_fn)
    except OSError as edata:
        if edata.errno != errno.ENOENT:
            output.perror(edata)
            return False
    try:
        to_fd = _creat(to_fn, mode=stat_data.st_mode)
    except OSError as edata:
        output.perror(edata);
        os.close(from_fd);
        return False
    os.fchmod(to_fd, stat_data.st_mode)
    try:
        _copy_fd(from_fd, to_fd)
    except OSError as edata:
        output.perror(edata, '%s -> %s' % (from_fn, to_fn))
        os.unlink(to_fn)
        return False
    finally:
        os.close(from_fd)
        os.close(to_fd)
    return True
예제 #7
0
파일: backup.py 프로젝트: pwil3058/pyquilt
 def remove_file(backup):
     try:
         if verbose:
             output.write('Removing %s\n' % backup)
         os.unlink(backup)
     except OSError as edata:
         output.perror(edata, backup)
         return False
     try:
         _remove_parents(backup)
     except IOError as edata:
         output.perror(edata, backup)
         return False
     return True
예제 #8
0
파일: backup.py 프로젝트: pwil3058/pyquilt
def ensure_nolinks_in_dir(in_dir, verbose=False):
    def onerror(exception):
        raise exception
    if not os.path.isdir(in_dir):
        return False
    try:
        for basedir, dirnames, filenames in os.walk(in_dir, onerror=onerror):
            for filename in filenames:
                filename = os.path.join(basedir, filename)
                if verbose:
                    output.write('Delinking %s\n' % filename)
                if not ensure_nolinks(filename):
                    return False
    except IOError as edata:
        output.perror(edata)
        return False
    return True
예제 #9
0
def get_files():
    '''Return a list of the files in the current directory.
    Omitting those that are quilt metadata files.'''
    files = []
    def onerror(exception):
        raise exception
    try:
        dirname = os.getcwd()
        for basedir, dirnames, filenames in os.walk(dirname, onerror=onerror):
            reldir = '' if basedir == dirname else os.path.relpath(basedir, dirname)
            if reldir.split(os.sep)[0] in [patchfns.QUILT_PC, patchfns.QUILT_PATCHES]:
                continue
            for entry in filenames:
                files.append(os.path.join(reldir, entry))
    except OSError as edata:
        output.perror(edata)
        return []
    return files
예제 #10
0
파일: fsutils.py 프로젝트: pwil3058/pyquilt
def files_in_dir(dirname, recurse=True, exclude_timestamp=True):
    '''Return a list of the files in the given directory.'''
    files = []
    if recurse:
        def onerror(exception):
            raise exception
        try:
            for basedir, dirnames, filenames in os.walk(dirname, onerror=onerror):
                reldir = '' if basedir == dirname else os.path.relpath(basedir, dirname)
                for entry in filenames:
                    if not exclude_timestamp or not entry == '.timestamp':
                        files.append(os.path.join(reldir, entry))
        except OSError as edata:
            output.perror(edata)
            return []
    else:
        for entry in os.listdir(dirname):
            if os.path.isdir(entry):
                continue
            if not exclude_timestamp or not entry == '.timestamp':
                files.append(entry)
    return files
예제 #11
0
파일: backup.py 프로젝트: pwil3058/pyquilt
 def restore_file(file_nm):
     backup = os.path.join(bu_dir, file_nm)
     file_nm = file_nm if to_dir is None else os.path.relpath(os.path.join(to_dir, file_nm))
     _create_parents(file_nm)
     try:
         stat_data = os.stat(backup)
     except OSError as edata:
         output.perror(edata, backup)
         return False
     if stat_data.st_size == 0:
         try:
             os.unlink(file_nm)
         except OSError as edata:
             if edata.errno != errno.ENOENT:
                 output.perror(edata, file_nm)
                 return False
         if verbose:
             output.write('Removing %s\n' % file_nm)
         if not keep:
             os.unlink(backup)
             _remove_parents(backup)
     else:
         if verbose:
             output.write('Restoring %s\n' % file_nm)
         try:
             os.unlink(file_nm)
         except OSError as edata:
             if edata.errno != errno.ENOENT:
                 raise
         if not _link_or_copy_file(backup, stat_data, file_nm):
             return False
         if not keep:
             os.unlink(backup)
             _remove_parents(backup)
         if touch:
             os.utime(file_nm, None)
         else:
             os.utime(file_nm, (stat_data.st_mtime, stat_data.st_mtime))
     return True
예제 #12
0
파일: backup.py 프로젝트: pwil3058/pyquilt
 def backup_file(file_nm):
     backup = os.path.join(bu_dir, file_nm)
     try:
         stat_data = os.stat(file_nm)
     except OSError as edata:
         missing_file = edata.errno == errno.ENOENT
     else:
         missing_file = False
     try:
         os.unlink(backup)
     except OSError as edata:
         if edata.errno != errno.ENOENT:
             output.perror(edata)
             return False
     _create_parents(backup)
     if missing_file:
         if verbose:
             output.write('New file %s\n' % file_nm)
         try:
             os.close(_creat(backup, mode=0666))
         except OSError as edata:
             output.perror(edata)
             return False
     else:
         if verbose:
             output.write('Copying %s\n' % file_nm)
         if stat_data.st_nlink == 1:
             result = _copy_file(file_nm, stat_data, backup)
             if result is not True:
                 return result
         else:
             result = _link_or_copy_file(file_nm, stat_data, backup)
             if result is not True:
                 return result
             result = ensure_nolinks(file_nm)
             if result is not True:
                 return result
         os.utime(backup, (stat_data.st_mtime, stat_data.st_mtime,))
     return True
예제 #13
0
def run_mail(args):
    patchfns.chdir_to_base_dir()
    if not shell.which('formail'):
        output.write("You have to install 'formail' to use 'quilt mail'")
        return cmd_result.ERROR
    if not args.opt_signature or args.opt_signature == '-':
        args.opt_signature = None
    else:
        try:
            args.opt_signature = open(args.opt_signature).read()
        except IOError as edata:
            output.perror(edata)
    if args.first_patch:
        args.first_patch = patchfns.find_first_patch() if args.first_patch == '-' else patchfns.find_patch(args.first_patch)
        if not args.first_patch:
            return cmd_result.ERROR
        if not args.last_patch:
            args.last_patch = args.first_patch
        else:
            args.last_patch = patchfns.find_last_patch() if args.last_patch == '-' else patchfns.find_patch(args.last_patch)
            if not args.last_patch:
                return cmd_result.ERROR
    if not args.opt_sender:
        hostname = socket.gethostname()
        args.opt_sender = '%s@%s' % (get_login_name(), hostname)
        if not re.match('^\S+@\S+\.\S+$', args.opt_sender):
            output.error('Could not determine the envelope sender address. Please use --sender.\n')
            return cmd_result.ERROR
    _dummy, args.opt_sender_address = email.utils.parseaddr(args.opt_sender)
    if not args.opt_charset:
        lc_all = os.getenv('LC_ALL', patchfns.ORIGINAL_LANG)
        if lc_all and lc_all.endswith('UTF-8'):
            args.opt_charset = 'UTF-8'
        else:
            args.opt_charset = 'ISO-8859-15'
    patches = patchfns.cat_series()
    if args.first_patch:
        first_index = patches.index(args.first_patch)
        last_index = patches.index(args.last_patch)
        if last_index < first_index:
            output.error('Patch %s not applied before patch %s\n' % (patchfns.print_patch(args.first_patch), patchfns.print_patch(args.first_patch)))
            return cmd_result.ERROR
        patches = patches[first_index:last_index + 1]
    total = len(patches)
    tmpdir = patchfns.gen_tempfile(asdir=True)
    atexit.register(lambda: not os.path.exists(tmpdir) or shutil.rmtree(tmpdir, ignore_errors=True))
    subject_map = {}
    patch_msgs = []
    for patch in patches:
        contents = fsutils.get_file_contents(patchfns.patch_file_name(patch))
        mailmsg = message_from_patch(contents, args.opt_charset)
        if mailmsg is False:
            subject = None
        else:
            patch_msgs.append(mailmsg)
            subject = mailmsg['Replace-Subject']
        if mailmsg is False or not subject:
            output.error('Unable to extract a subject header from %s\n' % patchfns.print_patch(patch))
            return cmd_result.ERROR
        if subject in subject_map:
            subject_map[subject].append(patch)
        else:
            subject_map[subject] = [patch]
    if len(subject_map) != len(patches):
        duplicates = []
        for key in sorted(subject_map):
            plist = subject_map[key]
            if len(plist) > 1:
                duplicates += plist
        output.error('Patches %s have duplicate subject headers.\n' % ', '.join([patchfns.print_patch(dup) for dup in duplicates]))
        return cmd_result.ERROR
    if args.opt_reply_to:
        if not os.path.exists(args.opt_reply_to):
            output.error('File %s does not exist\n' % args.opt_reply_to)
            return cmd_result.ERROR
        args.opt_reply_to = email.message_from_string(open(args.opt_reply_to).read())
        if not args.opt_subject:
            repto_subject = args.opt_reply_to['Subject']
            args.opt_subject = 'Re: %s' % re.sub('^([ \t]*[rR][eE]:[ \t]*)', '', repto_subject)
    intro = 'Message-Id: <%s>\n' % msgid(args)
    intro += 'User-Agent: pyquilt\n'
    last_ts = time.localtime()
    intro += time.strftime('Date: %a, %d %b %Y %H:%M:%S %z\n', last_ts)
    intro += 'From: %s\n' % (args.opt_from if args.opt_from else args.opt_sender)
    intro += 'To: %s\n' % (', '.join(args.opt_to) if args.opt_to else '')
    intro += 'Cc: %s\n' % (', '.join(args.opt_cc) if args.opt_cc else '')
    intro += 'Bcc: %s\n' % (', '.join(args.opt_bcc) if args.opt_bcc else '')
    if args.opt_reply_to:
        intro += in_reply_to_header(args.opt_reply_to)
        intro += references_header(args.opt_reply_to)
    intro += 'Subject-Prefix: [%s @num@/@total@]\n' % args.opt_prefix
    intro += 'Subject: %s\n\n' % (args.opt_subject if args.opt_subject else '')
    intro += ('%s\n\n' % args.opt_message) if args.opt_message else ''
    intro += ('-- \n%s\n' % args.opt_signature) if args.opt_signature else ''
    intro_message = email.message_from_string(intro)
    intro_message.set_charset(args.opt_charset)
    if not args.opt_message:
        introfile = patchfns.gen_tempfile()
        open(introfile, 'w').write(intro_message.as_string())
        result = shell.run_cmd('%s %s' % (os.getenv('EDITOR'), introfile))
        output.write(result.stdout)
        output.error(result.stderr)
        intro_message = email.message_from_string(open(introfile).read(), charset=args.opt_charset)
        os.remove(introfile)
        if result.eflags != 0:
            return cmd_result.ERROR
    subject = join_lines(intro_message['Subject'])
    if not subject:
        if not args.opt_message:
            savefile = patchfns.gen_tempfile()
            open(savefile, 'w').write(intro_message.as_string())
            output.error('Introduction has no subject header (saved as %s)\n' % savefile)
        else:
            output.error('Introduction has no subject header\n')
        return cmd_result.ERROR
    if args.opt_mbox:
        fsutils.touch(args.opt_mbox)
    subject_prefix = email.utils.quote(join_lines(intro_message['Subject-Prefix']))
    subject_prefix += ' ' if subject_prefix else ''
    subject_prefix = re.sub('@total@', str(total), subject_prefix)
    del intro_message['Subject-Prefix']
    pnum_fmt = '{0:0%s}' % len(str(total))
    pfx = re.sub('@num@', pnum_fmt.format(0), subject_prefix)
    intro_message.replace_header('Subject', pfx + intro_message['Subject'])
    remove_empty_headers(intro_message)
    for key in ['To', 'Cc', 'Bcc']:
        # Consolidate up the various recipient fields
        values = intro_message.get_all(key)
        if values:
            del intro_message[key]
            intro_message[key] = ', '.join(values)
    process_mail(intro_message, args)
    pnum = 0
    for msg in patch_msgs:
        msg.add_header('Content-Disposition', 'inline',  filename=patches[pnum])
        for key in intro_message.keys():
            if key.lower() not in ['message-id', 'references', 'in-reply-to', 'subject']:
                for value in intro_message.get_all(key):
                    msg[key] = value
        msg['References'] = get_reference_to(intro_message)
        msg.set_charset(args.opt_charset)
        for aclass in ['To', 'Cc', 'Bcc']:
            rclass = 'Recipient-' + aclass
            if msg.has_key(rclass):
                msg[aclass] = ',\n '.join(msg.get_all(rclass))
                del msg[rclass]
        pnum += 1
        ppfx = re.sub('@num@', pnum_fmt.format(pnum), subject_prefix)
        msg['Message-Id'] = msgid(args)
        msg['Subject'] = '%s%s' % (ppfx, msg['Replace-Subject']) if ppfx else msg['Replace-Subject']
        del msg['Replace-Subject']
        remove_empty_headers(msg)
        process_mail(msg, args)
    return cmd_result.OK