Example #1
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
Example #2
0
def apply_patch_text(text, indir=None, patch_args=""):
    from pyquilt_pkg import customization

    patch_opts = customization.get_default_opts("patch")
    if indir:
        cmd = "patch -d %s" % indir
    else:
        cmd = "patch"
    cmd += " %s %s" % (patch_opts, patch_args)
    return shell.run_cmd(cmd, input_text=text)
Example #3
0
def run_annotate(args):
    patchfns.chdir_to_base_dir()
    args.opt_patch = patchfns.find_applied_patch(args.opt_patch)
    opt_file = os.path.join(patchfns.SUBDIR, args.filename)
    if not args.opt_patch:
        return cmd_result.ERROR
    patches = []
    files = []
    next_patch = None
    for patch in patchfns.applied_patches():
        old_file = patchfns.backup_file_name(patch, opt_file)
        if os.path.isfile(old_file):
            patches.append(patch)
            files.append(old_file)
        if patch == args.opt_patch:
            next_patch = patchfns.next_patch_for_file(patch, opt_file)
            break
    if not next_patch:
        files.append(opt_file)
    else:
        files.append(patchfns.backup_file_name(next_patch, opt_file))
    if len(patches) == 0:
        for line in open(files[-1]).readlines():
            output.write('\t%s\n' % line)
        return cmd_result.OK
    difftxt = ''
    for index in range(len(patches)):
        difftxt += annotation_for(files[index], files[index + 1], index + 1)
    template = patchfns.gen_tempfile()
    open(template, 'w').write('\n' * len(open(files[0]).readlines()))
    shell.run_cmd('patch %s' % template, difftxt)
    annotations = [line.rstrip() for line in open(template).readlines()]
    os.remove(template)
    output.start_pager()
    if os.path.exists(files[-1]):
        for annotation, line in zip(annotations, open(files[-1]).readlines()):
            output.write('%s\t%s' % (annotation, line))
    output.write('\n')
    for index, patch in zip(range(len(patches)), patches):
        output.write('%s\t%s\n' % (index + 1, patchfns.print_patch(patch)))
    output.wait_for_pager()
    return cmd_result.OK
Example #4
0
def run_edit(args):
    patchfns.chdir_to_base_dir()
    if patchfns.pyquilt_command('add %s' % ' '.join(args.filelist)) not in [0, 2]:
        return cmd_result.ERROR
    efilelist = args.filelist if not patchfns.SUBDIR else [os.path.join(patchfns.SUBDIR, fnm) for fnm in args.filelist]
    os.environ['LANG'] = patchfns.ORIGINAL_LANG
    result = shell.run_cmd('%s %s' % (os.getenv('EDITOR'), ' '.join(efilelist)))
    output.error(result.stderr)
    output.write(result.stdout)
    status = cmd_result.OK if result.eflags == 0 else cmd_result.ERROR
    for filename in args.filelist:
        efname = filename if not patchfns.SUBDIR else os.path.join(patchfns.SUBDIR, filename)
        if not os.path.exists(efname):
            patchfns.pyquilt_command('revert %s' % filename)
            status = cmd_result.ERROR
    return status
Example #5
0
def process_mail(message, args):
    if args.opt_send:
        sendmail_cmd = '%s %s --f %s ' % (os.getenv('QUILT_SENDMAIL', 'sendmail'), os.getenv('QUILT_SENDMAIL_ARGS', ''), args.opt_sender)
        sendmail_cmd += extract_recipients(message)
        output.write(sendmail_cmd)
        del message['Bcc']
        result = shell.run_cmd(sendmail_cmd, message.as_string(False))
        output.write(result.stdout)
        output.error(result.stderr)
    else:
        from_date = time.strftime('+%a %b %e %H:%M:%S %Y')
        fobj = open(args.opt_mbox, 'a')
        fobj.write('From %s %s\n' % (args.opt_sender_address, from_date))
        for field, value in message.items():
            fobj.write('%s: %s\n' % (field, value))
        fobj.write('\n')
        for line in message.get_payload().splitlines(True):
            fobj.write(re.sub('^From ', '>From ', line))
        fobj.close()
Example #6
0
def annotation_for(old_file, new_file, annotation):
    """Return diff for annotation for changes from osd_file to new_file"""
    if not os.path.exists(old_file) or os.path.getsize(old_file) == 0:
        old_file = '/dev/null'
    if not os.path.exists(new_file) or os.path.getsize(new_file) == 0:
        new_file = '/dev/null'
    result = shell.run_cmd('diff -e "%s" "%s"' % (old_file, new_file))
    if result.eflags > 1:
        output.error(result.stderr)
        sys.exit(result.eflags)
    difftxt = ''
    start_cre = re.compile('^(\d+)(,\d+)?([acd])$')
    end_cre = re.compile('^\.$')
    lines = result.stdout.splitlines(True)
    index = 0
    aline = '%s\n' % annotation
    while index < len(lines):
        match = start_cre.match(lines[index])
        if match:
            difftxt += lines[index]
            start = int(match.group(1))
            if match.group(3) == 'a':
                index += 1
                while end_cre.match(lines[index]) is None:
                    difftxt += aline
                    index += 1
                difftxt += lines[index]
            elif match.group(3) == 'c':
                end = int(match.group(2)[1:]) if match.group(2) is not None else start
                cnt = end - start + 1
                index += cnt + 1
                difftxt += aline * cnt
                assert end_cre.match(lines[index])
                difftxt += lines[index]
            else:
                assert match.group(3) == 'd'
            index += 1
        else:
            assert False
            index += 1
    return difftxt
Example #7
0
def run_grep(args):
    patchfns.chdir_to_base_dir()
    problem_args = [] # i.e. those wit optional arguments
    for arg in ['--color', '--colour']:
        while arg in args.remainder_of_args:
            problem_args.append(arg)
            args.remainder_of_args.remove(arg)
    grep_opts, grep_args = getopt.getopt(args.remainder_of_args, grep_options, grep_long_options)
    opt_list = make_opt_list(grep_opts) + problem_args
    if expect_pattern(grep_opts):
        files = grep_args[1:]
        opt_list += grep_args[0:1]
    else:
        files = grep_args
    if not files:
        files = get_files()
    if len(files) == 1 and '-h' not in opt_list and '--no-filename' not in opt_list:
        opt_list.append('-H')
    result = shell.run_cmd(['grep'] + opt_list + files)
    output.write(result.stdout)
    output.error(result.stderr)
    return result.eflags
Example #8
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