Beispiel #1
0
def get_patch_files(path, strip_level=1):
    try:
        buf = fsutils.get_file_contents(path)
    except IOError:
        return (False, 'Problem(s) open file "%s" not found' % path)
    obj = patchlib.Patch.parse_text(buf)
    return obj.get_file_paths(int(strip_level))
Beispiel #2
0
def set_patch_descr(path, text):
    if os.path.exists(path):
        patch_obj = patchlib.Patch.parse_text(fsutils.get_file_contents(path))
    else:
        patch_obj = patchlib.Patch()
    patch_obj.set_description(text)
    return _write_via_temp(path, str(patch_obj))
Beispiel #3
0
def merge_patches(old, new, opt_desc):
    """Return the merge of the old and new patches"""
    old_desc = patchfns.gen_tempfile()
    open(old_desc, 'w').write(putils.get_patch_descr(old))
    new_desc = patchfns.gen_tempfile()
    open(new_desc, 'w').write(putils.get_patch_descr(new))
    if opt_desc is None:
        if os.path.getsize(old_desc) == 0:
            opt_desc = 'n'
        elif os.path.getsize(new_desc) == 0:
            opt_desc = 'o'
        if opt_desc is None:
            result = shell.run_cmd('diff -u %s %s' % (old_desc, new_desc))
            diff_lines = result.stdout.splitlines(True)
            if len(diff_lines) > 2:
                output.error('Patch headers differ:\n')
                output.error(''.join(diff_lines[2:]))
                output.error('Please use -d {o|a|n} to specify which patch header(s) to keep.\n')
                os.remove(old_desc)
                os.remove(new_desc)
                return False
    patchtext = open(old_desc).read() if opt_desc != 'n' else ''
    if opt_desc == 'a':
        patchtext += '---\n'
    if opt_desc == 'o':
        patchtext += putils.get_patch_diff(new)
    else:
        patchtext += fsutils.get_file_contents(new)
    os.remove(old_desc)
    os.remove(new_desc)
    return patchtext
Beispiel #4
0
def set_patch_hdr(path, text, omit_diffstat=False):
    if os.path.exists(path):
        patch_obj = patchlib.Patch.parse_text(fsutils.get_file_contents(path))
    else:
        patch_obj = patchlib.Patch()
    if omit_diffstat:
        dummy = patchlib.Patch.parse_text(text)
        dummy.set_diffstat("")
        hdr = dummy.get_header()
        text = "" if hdr is None else str(hdr)
    patch_obj.set_header(text)
    return _write_via_temp(path, str(patch_obj))
Beispiel #5
0
def run_import(args):
    patchfns.chdir_to_base_dir()
    if args.opt_patch and len(args.patchfiles) > 1:
        output.error('Option `-P\' can only be used when importing a single patch\n')
        return cmd_result.ERROR
    patch_args = ('-p%s' % args.opt_strip) if args.opt_strip else ''
    if args.opt_reverse:
        patch_args = '-R' if not patch_args else patch_args + ' -R'
    before = patchfns.patch_after(patchfns.top_patch())
    for patch_file in args.patchfiles:
        patch = args.opt_patch if args.opt_patch else os.path.basename(patch_file)
        patch_file_name = patchfns.find_patch_file(patch_file)
        if not patch_file_name:
            return cmd_result.ERROR
        merged = False
        if patchfns.is_applied(patch):
            output.error('Patch %s is applied\n' % patchfns.print_patch(patch))
            return cmd_result.ERROR
        dest = patchfns.patch_file_name(patch)
        if patchfns.patch_in_series(patch):
            if patch_file_name == dest:
                output.error('Patch %s already exists in series.\n' % patchfns.print_patch(patch))
                return cmd_result.ERROR
            if not args.opt_force:
                output.error('Patch %s exists. Replace with -f.\n' % patchfns.print_patch(patch))
                return cmd_result.ERROR_SUGGEST_FORCE
            if args.opt_desc != 'n':
                merged_patch = merge_patches(dest, patch_file_name, args.opt_desc)
                if merged_patch is False:
                    return cmd_result.ERROR
                merged = True
            output.error('Replacing patch %s with new version\n' % patchfns.print_patch(patch))
        elif os.path.exists(dest):
            output.write('Importing patch %s\n' % patchfns.print_patch(patch))
        else:
            output.write('Importing patch %s (stored as %s)\n' % (patch_file, patchfns.print_patch(patch)))
            dest_dir = os.path.dirname(dest)
            if not os.path.exists(dest_dir):
                os.makedirs(dest_dir)
        try:
            if merged:
                fsutils.set_file_contents(dest, merged_patch)
            else:
                # just in case dest == patch_file do it this way
                text = fsutils.get_file_contents(patch_file_name)
                fsutils.set_file_contents(dest, text)
        except IOError as edata:
            output.error('Failed to import patch %s\n' % patchfns.print_patch(patch))
            return cmd_result.ERROR
        if not patchfns.patch_in_series(patch) and not patchfns.insert_in_series(patch, patch_args, before):
            output.error('Failed to insert patch %s into file series\n' % patchfns.print_patch(patch))
    return cmd_result.OK
Beispiel #6
0
def apply_patch_temporarily(workdir, patch, files=None):
    patch_file = patch_file_name(patch)
    args = patch_args(patch)
    srcdir = os.path.join(QUILT_PC, patch)
    if not backup.restore(srcdir, to_dir=workdir, filelist=files, keep=True):
        output.error('Failed to copy files to temporary directory\n')
        return False
    if os.path.isfile(patch_file) and os.path.getsize(patch_file) > 0:
        text = fsutils.get_file_contents(patch_file)
        result = putils.apply_patch(indir=workdir, patch_args=' '.join(args) + ' --no-backup-if-mismatch -Ef', patch_file=patch_file)
        if result.eflags != 0:
            # Generating a relative diff for a subset of files in
            # the patch will fail. Also, if a patch was force
            # applied, we know that it won't apply cleanly. In
            # all other cases, print a warning.
            if not os.path.isfile(os.path.join(QUILT_PC, patch + '~refresh')) and len(files) == 0:
                output.error('Failed to patch temporary files\n')
                return False
    return True
Beispiel #7
0
def get_patch_diff(path, file_list=None, strip_level=0):
    return get_patch_diff_fm_text(fsutils.get_file_contents(path), file_list, strip_level)
Beispiel #8
0
def get_patch_hdr(path, omit_diffstat=False):
    try:
        buf = fsutils.get_file_contents(path)
    except IOError:
        return ""
    return get_patch_hdr_fm_text(buf, omit_diffstat)
Beispiel #9
0
def get_patch_descr(path):
    try:
        buf = fsutils.get_file_contents(path)
    except IOError:
        return ""
    return get_patch_descr_fm_text(buf)
Beispiel #10
0
def apply_patch(patch_file, indir=None, patch_args=""):
    text = fsutils.get_file_contents(patch_file)
    return apply_patch_text(text, indir=indir, patch_args=patch_args)
Beispiel #11
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