예제 #1
0
파일: mail.py 프로젝트: hasturkun/stgit
def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options):
    """Send the message using the given SMTP server
    """
    smtpuser, smtppassword, smtpusetls = __smtp_credentials

    try:
        s = smtplib.SMTP(smtpserver)
    except Exception as err:
        raise CmdException(str(err))

    s.set_debuglevel(0)
    try:
        if smtpuser and smtppassword:
            s.ehlo()
            if smtpusetls:
                if not hasattr(socket, 'ssl'):
                    raise CmdException(
                        "cannot use TLS - no SSL support in Python")
                s.starttls()
                s.ehlo()
            s.login(smtpuser, smtppassword)

        result = s.sendmail(from_addr, to_addr_list, msg)
        if len(result):
            print(
                "mail server refused delivery for the following recipients:",
                result,
            )
    except Exception as err:
        raise CmdException(str(err))

    s.quit()
예제 #2
0
def __import_tarfile(tarpath, options):
    """Import patch series from a tar archive"""
    import tarfile

    assert tarfile.is_tarfile(tarpath)

    tar = tarfile.open(tarpath, 'r')
    names = tar.getnames()

    # verify paths in the tarfile are safe
    for n in names:
        if n.startswith('/'):
            raise CmdException("Absolute path found in %s" % tarpath)
        if n.find("..") > -1:
            raise CmdException("Relative path found in %s" % tarpath)

    # find the series file
    for seriesfile in names:
        if seriesfile.endswith('/series') or seriesfile == 'series':
            break
    else:
        raise CmdException("no 'series' file found in %s" % tarpath)

    # unpack into a tmp dir
    with tempfile.TemporaryDirectory('.stg') as tmpdir:
        tar.extractall(tmpdir)
        __import_series(os.path.join(tmpdir, seriesfile), options)
예제 #3
0
def func(parser, options, args):
    """Integrate a GNU diff patch into the current patch"""
    if len(args) > 1:
        parser.error('incorrect number of arguments')

    repository = directory.repository
    stack = repository.get_stack()

    check_local_changes(repository)
    check_conflicts(repository.default_iw)
    check_head_top_equal(stack)

    if len(args) == 1:
        filename = args[0]
    else:
        filename = None

    applied = stack.patchorder.applied
    if not applied:
        raise CmdException('No patches applied')

    current = applied[-1]

    if filename:
        if os.path.exists(filename):
            out.start('Folding patch "%s"' % filename)
            with io.open(filename, 'rb') as f:
                diff = f.read()
        else:
            raise CmdException('No such file: %s' % filename)
    else:
        out.start('Folding patch from stdin')
        diff = sys.stdin.buffer.read()

    if options.threeway:
        top_patch = stack.patches.get(current)
        apply_patch(
            stack,
            diff,
            base=top_patch.commit.data.parent,
            strip=options.strip,
            reject=options.reject,
        )
    elif options.base:
        apply_patch(
            stack,
            diff,
            base=git_commit(options.base, repository),
            reject=options.reject,
            strip=options.strip,
        )
    else:
        apply_patch(
            stack,
            diff,
            strip=options.strip,
            reject=options.reject,
        )

    out.done()
예제 #4
0
def __send_message_smtp(smtpserver, from_addr, to_addr_list, msg, options):
    """Send the message using the given SMTP server
    """
    smtpuser, smtppassword, smtpusetls = __smtp_credentials

    try:
        s = smtplib.SMTP(smtpserver)
    except Exception as err:
        raise CmdException(str(err))

    s.set_debuglevel(0)
    try:
        if smtpuser and smtppassword:
            s.ehlo()
            if smtpusetls:
                try:
                    s.starttls()
                except (smtplib.SMTPException, RuntimeError) as e:
                    # RuntimeError indicates that Python lacks SSL support.
                    # SMTPException indicates that server does not do STARTTLS.
                    raise CmdException("cannot use TLS: %s" % e)
                s.ehlo()
            s.login(smtpuser, smtppassword)

        result = s.sendmail(from_addr, to_addr_list, msg)
        if len(result):
            print(
                "mail server refused delivery for the following recipients:", result,
            )
    except Exception as err:
        raise CmdException(str(err))

    s.quit()
예제 #5
0
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: "%s"' % name)
        elif name in stack.patches:
            raise CmdException('%s: patch already exists' % name)
    else:
        parser.error('incorrect number of arguments')

    if options.verbose:
        verbose = options.verbose
    else:
        verbose = config.getbool('stgit.new.verbose') or False

    cd = CommitData(
        tree=stack.head.data.tree,
        parents=[stack.head],
        message='',
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(
        stack.repository,
        cd,
        message=options.message,
        author=options.author(cd.author),
        trailers=options.trailers,
        edit=(not options.save_template and options.message is None),
        verbose=verbose,
    )

    if options.save_template:
        options.save_template(cd.message)
        return utils.STGIT_SUCCESS

    if not options.no_verify:
        cd = run_commit_msg_hook(stack.repository, cd)

    if name is None:
        name = stack.patches.make_name(cd.message_str)

    # Write the new patch.
    check_head_top_equal(stack)
    trans = StackTransaction(stack)
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.execute('new: %s' % name)
예제 #6
0
def func(parser, options, args):
    """Pushes the given patches or the first unapplied onto the stack."""
    stack = directory.repository.current_stack
    iw = stack.repository.default_iw
    clean_iw = (not options.keep and iw) or None
    trans = transaction.StackTransaction(stack,
                                         'push',
                                         check_clean_iw=clean_iw)

    if options.number == 0:
        # explicitly allow this without any warning/error message
        return

    if not trans.unapplied:
        raise CmdException('No patches to push')

    if options.all:
        patches = list(trans.unapplied)
    elif options.number is not None:
        patches = trans.unapplied[:options.number]
    elif not args:
        patches = [trans.unapplied[0]]
    else:
        try:
            patches = parse_patches(args, trans.unapplied)
        except CmdException as e:
            try:
                patches = parse_patches(args, trans.applied)
            except CmdException:
                raise e
            else:
                raise CmdException(
                    'Patch%s already applied: %s' %
                    ('es' if len(patches) > 1 else '', ', '.join(patches)))

    assert patches

    if options.reverse:
        patches.reverse()

    if options.set_tree:
        for pn in patches:
            trans.push_tree(pn)
    else:
        try:
            if options.merged:
                merged = set(trans.check_merged(patches))
            else:
                merged = set()
            for pn in patches:
                trans.push_patch(pn,
                                 iw,
                                 allow_interactive=True,
                                 already_merged=pn in merged)
        except transaction.TransactionHalted:
            pass
    return trans.run(iw)
예제 #7
0
def func(parser, options, args):
    """Generate a new commit for the current or given patch."""

    if options.spill:
        if (
            len(args) > 0
            or options.index
            or options.edit
            or options.update
            or options.patch
            or options.force
            or options.no_verify
            or options.sign_str
        ):
            raise CmdException('--spill option does not take any arguments or options')
        return __refresh_spill(annotate=options.annotate)
    else:
        # Catch illegal argument combinations.
        is_path_limiting = bool(args or options.update)
        if options.index and is_path_limiting:
            raise CmdException('Only full refresh is available with the --index option')

        if options.index and options.force:
            raise CmdException(
                'You cannot --force a full refresh when using --index mode'
            )

        if options.update and options.submodules:
            raise CmdException(
                '--submodules is meaningless when only updating modified files'
            )

        if options.index and options.submodules:
            raise CmdException(
                '--submodules is meaningless when keeping the current index'
            )

        # If submodules was not specified on the command line, infer a default
        # from configuration.
        if options.submodules is None:
            options.submodules = config.getbool('stgit.refreshsubmodules')

        return __refresh(
            args,
            force=options.force,
            target_patch=options.patch,
            message=options.message,
            author=options.author,
            sign_str=options.sign_str,
            annotate=options.annotate,
            use_temp_index=is_path_limiting,
            refresh_from_index=options.index,
            only_update_patchfiles=options.update,
            include_submodules=options.submodules,
            no_verify=options.no_verify,
            invoke_editor=options.edit,
        )
예제 #8
0
def func(parser, options, args):
    """Show the patches modifying a file."""
    repository = directory.repository
    stack = repository.get_stack(options.branch)

    if not stack.patchorder.applied:
        raise CmdException('No patches applied')

    iw = repository.default_iw

    if not args:
        files = iw.changed_files(stack.head.data.tree)
    else:
        files = iw.ls_files(stack.head.data.tree, args)

    if not files:
        raise CmdException('No files specified or no local changes')

    directory.cd_to_topdir()

    # Find set of revisions that modify the selected files.
    revs = set(
        repository.run(
            ['git', 'rev-list', '--stdin', stack.base.sha1 + '..' + stack.top.sha1]
        )
        .raw_input('--\n' + '\n'.join(files))
        .output_lines()
    )

    diff_lines = []
    for pn in stack.patchorder.applied:
        commit = stack.patches[pn]
        if commit.sha1 not in revs:
            continue
        if options.diff:
            diff_lines.extend(
                [
                    b'-' * 79,
                    pn.encode('utf-8'),
                    b'-' * 79,
                    commit.data.message,
                    b'---',
                    b'',
                    repository.diff_tree(
                        commit.data.parent.data.tree,
                        commit.data.tree,
                        pathlimits=files,
                        diff_opts=options.diff_flags + color_diff_flags(),
                    ),
                ]
            )
        else:
            out.stdout(pn)

    if options.diff:
        pager(b'\n'.join(diff_lines))
예제 #9
0
def __cleanup_branch(name, force=False):
    stack = directory.repository.get_stack(name)
    if stack.protected:
        raise CmdException('This branch is protected. Clean up is not permitted')
    if not force and stack.patchorder.all:
        raise CmdException('Cannot clean up: the series still contains patches')

    out.start('Cleaning up branch "%s"' % name)
    stack.cleanup()
    out.done()
예제 #10
0
def __delete_branch(doomed_name, force=False):
    doomed = stack.Series(doomed_name)

    if __is_current_branch(doomed_name):
        raise CmdException('Cannot delete the current branch')
    if doomed.get_protected():
        raise CmdException('This branch is protected. Delete is not permitted')

    out.start('Deleting branch "%s"' % doomed_name)
    doomed.delete(force)
    out.done()
예제 #11
0
파일: mail.py 프로젝트: xcode2010/stgit
def __parse_addresses(msg):
    """Return a two elements tuple: (from, [to])"""
    from_addr_list = __addr_list(msg, 'From')
    if len(from_addr_list) == 0:
        raise CmdException('No "From" address')

    to_addr_list = (__addr_list(msg, 'To') + __addr_list(msg, 'Cc') +
                    __addr_list(msg, 'Bcc'))
    if len(to_addr_list) == 0:
        raise CmdException('No "To/Cc/Bcc" addresses')

    return (from_addr_list[0], set(to_addr_list))
예제 #12
0
def get_patch(stack, given_patch):
    """Get the name of the patch we are to refresh."""
    if given_patch:
        patch_name = given_patch
        if not stack.patches.exists(patch_name):
            raise CmdException('%s: no such patch' % patch_name)
        return patch_name
    else:
        if not stack.patchorder.applied:
            raise CmdException(
                'Cannot refresh top patch because no patches are applied')
        return stack.patchorder.applied[-1]
예제 #13
0
def func(parser, options, args):
    """Import a commit object as a new patch
    """
    if not args:
        parser.error('incorrect number of arguments')

    if options.file and not options.fold:
        parser.error('--file can only be specified with --fold')

    if not options.unapplied:
        check_local_changes()
        check_conflicts()
        check_head_top_equal(crt_series)

    if options.ref_branch:
        remote_series = Series(options.ref_branch)
    else:
        remote_series = crt_series

    applied = remote_series.get_applied()
    unapplied = remote_series.get_unapplied()
    try:
        patches = parse_patches(args, applied + unapplied, len(applied))
        commit_id = None
    except CmdException:
        if len(args) > 1:
            raise
        # no patches found, try a commit id
        commit_id = git_id(remote_series, args[0])

    if not commit_id and len(patches) > 1:
        if options.name:
            raise CmdException('--name can only be specified with one patch')
        if options.parent:
            raise CmdException('--parent can only be specified with one patch')

    if options.update and not crt_series.get_current():
        raise CmdException('No patches applied')

    if commit_id:
        # Try to guess a patch name if the argument was <branch>:<patch>
        try:
            patchname = args[0].split(':')[1]
        except IndexError:
            patchname = None
        __pick_commit(commit_id, patchname, options)
    else:
        if options.unapplied:
            patches.reverse()
        for patch in patches:
            __pick_commit(git_id(remote_series, patch), patch, options)

    print_crt_patch(crt_series)
예제 #14
0
def func(parser, options, args):
    """Integrate a GNU diff patch into the current patch
    """
    if len(args) > 1:
        parser.error('incorrect number of arguments')

    check_local_changes()
    check_conflicts()
    check_head_top_equal(crt_series)

    if len(args) == 1:
        filename = args[0]
    else:
        filename = None

    current = crt_series.get_current()
    if not current:
        raise CmdException('No patches applied')

    if filename:
        if os.path.exists(filename):
            out.start('Folding patch "%s"' % filename)
        else:
            raise CmdException('No such file: %s' % filename)
    else:
        out.start('Folding patch from stdin')

    if options.threeway:
        crt_patch = crt_series.get_patch(current)
        bottom = crt_patch.get_bottom()
        git.apply_patch(
            filename=filename,
            base=bottom,
            strip=options.strip,
            reject=options.reject,
        )
    elif options.base:
        git.apply_patch(
            filename=filename,
            reject=options.reject,
            strip=options.strip,
            base=git_id(crt_series, options.base),
        )
    else:
        git.apply_patch(
            filename=filename,
            strip=options.strip,
            reject=options.reject,
        )

    out.done()
예제 #15
0
def func(parser, options, args):
    if len(args) != 1:
        parser.error('incorrect number of arguments')
    name = args[0]

    stack = directory.repository.current_stack
    iw = stack.repository.default_iw

    check_head_top_equal(stack)
    if not options.keep:
        check_index_and_worktree_clean(stack)

    trans = transaction.StackTransaction(stack)

    if name not in trans.all_patches:
        candidates = [pn for pn in trans.all_patches if name in pn]
        if len(candidates) == 1:
            name = candidates[0]
        elif len(candidates) > 1:
            out.info('Possible patches:\n  %s' % '\n  '.join(candidates))
            raise CmdException('Ambiguous patch name "%s"' % name)
        elif re.match('[0-9A-Fa-f]{4,40}$', name):
            sha1 = name
            name = stack.patches.name_from_sha1(sha1)
            if not name:
                raise CmdException('No patch associated with %s' % sha1)
        else:
            raise CmdException('Patch "%s" does not exist' % name)

    if name in trans.applied:
        to_pop = set(trans.applied[trans.applied.index(name) + 1:])
        popped_extra = trans.pop_patches(lambda pn: pn in to_pop)
        assert not popped_extra
    elif name in trans.unapplied:
        try:
            to_push = trans.unapplied[:trans.unapplied.index(name) + 1]
            if options.merged:
                merged = set(trans.check_merged(to_push))
            else:
                merged = set()
            for pn in to_push:
                trans.push_patch(pn,
                                 iw,
                                 allow_interactive=True,
                                 already_merged=pn in merged)
        except transaction.TransactionHalted:
            pass
    else:
        raise CmdException('Cannot goto a hidden patch')
    return trans.execute('goto', iw)
예제 #16
0
def func(parser, options, args):
    """Sink patches down the stack."""
    stack = directory.repository.current_stack

    if options.to and options.to not in stack.patchorder.applied:
        raise CmdException('Cannot sink below %s since it is not applied' %
                           options.to)

    if len(args) > 0:
        patches = parse_patches(args, stack.patchorder.all)
    else:
        # current patch
        patches = list(stack.patchorder.applied[-1:])

    if not patches:
        raise CmdException('No patches to sink')
    if options.to and options.to in patches:
        raise CmdException('Cannot have a sinked patch as target')

    unapplied_rem = [p for p in stack.patchorder.unapplied if p not in patches]
    applied_rem = [p for p in stack.patchorder.applied if p not in patches]
    insert_idx = applied_rem.index(options.to) if options.to else 0
    stay_applied, re_applied = applied_rem[:insert_idx], applied_rem[
        insert_idx:]

    if options.nopush:
        applied = stay_applied + patches
        unapplied = re_applied + unapplied_rem
    else:
        applied = stay_applied + patches + re_applied
        unapplied = unapplied_rem

    iw = stack.repository.default_iw

    check_head_top_equal(stack)
    if not options.keep:
        check_index_and_worktree_clean(stack)

    trans = transaction.StackTransaction(stack)

    try:
        trans.reorder_patches(applied,
                              unapplied,
                              iw=iw,
                              allow_interactive=True)
    except transaction.TransactionHalted:
        pass
    return trans.execute('sink', iw)
예제 #17
0
def func(parser, options, args):
    if len(args) > 1:
        parser.error('incorrect number of arguments')
    elif len(args) == 1:
        filename = args[0]
    elif options.url:
        raise CmdException('URL argument required')
    else:
        filename = None

    if not options.url and filename:
        filename = os.path.abspath(filename)

    directory.cd_to_topdir()

    repository = directory.repository
    stack = repository.current_stack

    check_local_changes(repository)
    check_conflicts(repository.default_iw)
    check_head_top_equal(stack)

    if options.url:
        __import_url(filename, options)
    elif options.series:
        __import_series(filename, options)
    elif options.mail or options.mbox:
        __import_mail(filename, options)
    else:
        __import_file(filename, options)
예제 #18
0
def func(parser, options, args):
    """Show the files modified by a patch (or the current patch)
    """
    if options.bare and options.stat:
        raise CmdException('Cannot specify both --bare and --stat')
    if len(args) == 0:
        patch = 'HEAD'
    elif len(args) == 1:
        patch = args[0]
    else:
        parser.error('incorrect number of arguments')

    rev1 = git_id(crt_series, '%s^' % patch)
    rev2 = git_id(crt_series, '%s' % patch)

    if options.stat:
        output = gitlib.diffstat(
            git.diff(rev1=rev1, rev2=rev2, diff_flags=options.diff_flags))
    elif options.bare:
        output = git.barefiles(rev1, rev2)
    else:
        output = git.files(rev1, rev2, diff_flags=options.diff_flags)
    if output:
        if not output.endswith('\n'):
            output += '\n'
        out.stdout_raw(output)
예제 #19
0
def __import_mbox(filename, options):
    """Import a series from an mbox file
    """
    if filename:
        namedtemp = None
    else:
        from tempfile import NamedTemporaryFile
        stdin = os.fdopen(sys.__stdin__.fileno(), 'rb')
        namedtemp = NamedTemporaryFile('wb', suffix='.mbox', delete=False)
        namedtemp.write(stdin.read())
        namedtemp.close()
        filename = namedtemp.name

    try:
        try:
            mbox = mailbox.mbox(filename,
                                message_from_binary_file,
                                create=False)
        except Exception as ex:
            raise CmdException('error parsing the mbox file: %s' % str(ex))

        with closing(mbox):
            for msg in mbox:
                (message, author_name, author_email, author_date,
                 diff) = parse_mail(msg)
                __create_patch(None, message, author_name, author_email,
                               author_date, diff, options)
    finally:
        if namedtemp is not None:
            os.unlink(namedtemp.name)
예제 #20
0
def __import_file(filename, options, patch=None):
    """Import a patch from a file or standard input
    """
    pname = None
    if filename:
        (f, pname) = __get_handle_and_name(filename)
    else:
        f = os.fdopen(sys.__stdin__.fileno(), 'rb')

    if patch:
        pname = patch
    elif not pname:
        pname = filename

    if options.mail:
        try:
            msg = message_from_binary_file(f)
        except Exception as ex:
            raise CmdException('error parsing the e-mail file: %s' % str(ex))
        (message, author_name, author_email, author_date,
         diff) = parse_mail(msg)
    else:
        patch_str = f.read()
        (message, author_name, author_email, author_date,
         diff) = parse_patch(patch_str, contains_diff=True)

    if filename:
        f.close()

    __create_patch(pname, message, author_name, author_email, author_date,
                   diff, options)
예제 #21
0
def __send_message(msg_type, tmpl, options, *args):
    """Message sending dispatcher.
    """
    domain = options.domain or config.get('stgit.domain')

    if domain:
        if sys.version_info < (3, 2):
            raise CmdException("Setting domain requires Python version 3.2+")
        msg_id = email.utils.make_msgid('stgit', domain=domain)
    else:
        msg_id = email.utils.make_msgid('stgit')

    if msg_type == 'cover':
        assert len(args) == 1, 'too many args for msg_type == "cover"'
        patches = args[0]
        msg = __build_cover(tmpl, msg_id, options, patches)
        outstr = 'the cover message'
    elif msg_type == 'patch':
        patch, patch_nr, total_nr, ref_id = args
        msg = __build_message(tmpl, msg_id, options, patch, patch_nr, total_nr,
                              ref_id)
        outstr = 'patch "%s"' % patch
    else:
        raise AssertionError('invalid msg_type: %s' %
                             msg_type)  # pragma: no cover

    if hasattr(msg, 'as_bytes'):
        msg_bytes = msg.as_bytes(options.mbox)
    else:
        msg_bytes = msg.as_string(options.mbox)
        # Python 3.3 only has Message.as_string(). We encode it back to bytes
        # and hope for the best.
        if isinstance(msg_bytes, text):
            msg_bytes = msg_bytes.encode('utf-8')
    if options.mbox:
        out.stdout_bytes(msg_bytes + b'\n')
        return msg_id

    if not options.git:
        from_addr, to_addrs = __parse_addresses(msg)
        out.start('Sending ' + outstr)

    smtpserver = options.smtp_server or config.get('stgit.smtpserver')
    if options.git:
        __send_message_git(msg_bytes, msg['From'], options)
    elif smtpserver.startswith('/'):
        # Use the sendmail tool
        __send_message_sendmail(smtpserver, msg_bytes)
    else:
        # Use the SMTP server (we have host and port information)
        __send_message_smtp(smtpserver, from_addr, to_addrs, msg_bytes,
                            options)

    # give recipients a chance of receiving related patches in correct order
    if msg_type == 'cover' or (msg_type == 'patch' and patch_nr < total_nr):
        sleep = options.sleep or config.getint('stgit.smtpdelay')
        time.sleep(sleep)
    if not options.git:
        out.done()
    return msg_id
예제 #22
0
def func(parser, options, args):
    stack = directory.repository.current_stack
    patches = parse_patches(args, list(stack.patchorder.all))
    if len(patches) < 2:
        raise CmdException('Need at least two patches')
    if options.name and not stack.patches.is_name_valid(options.name):
        raise CmdException('Patch name "%s" is invalid' % options.name)
    return _squash(
        stack,
        stack.repository.default_iw,
        options.name,
        options.message,
        options.save_template,
        patches,
        options.no_verify,
    )
예제 #23
0
파일: reset.py 프로젝트: wberrier/stgit
def func(parser, options, args):
    stack = directory.repository.current_stack
    iw = stack.repository.default_iw
    if len(args) >= 1:
        ref, patches = args[0], args[1:]
        state = log.get_log_entry(
            stack.repository, ref, stack.repository.rev_parse(ref)
        )
    elif options.hard:
        iw.checkout_hard(stack.head.data.tree)
        return utils.STGIT_SUCCESS
    else:
        raise CmdException('Wrong options or number of arguments')

    trans = transaction.StackTransaction(
        stack, 'reset', discard_changes=options.hard, allow_bad_head=True,
    )
    try:
        if patches:
            log.reset_stack_partially(trans, iw, state, patches)
        else:
            log.reset_stack(trans, iw, state)
    except transaction.TransactionHalted:
        pass
    return trans.run(iw, allow_bad_head=not patches)
예제 #24
0
파일: rebase.py 프로젝트: lamby/stgit
def func(parser, options, args):
    """Rebase the current stack
    """
    if len(args) != 1:
        parser.error('incorrect number of arguments')

    repository = directory.repository
    stack = repository.get_stack()
    iw = repository.default_iw

    if stack.protected:
        raise CmdException('This branch is protected. Rebase is not permitted')

    target = git_commit(args[0], repository)

    applied = stack.patchorder.applied

    retval = prepare_rebase(stack, 'rebase')
    if retval:
        return retval

    rebase(stack, iw, target)
    if not options.nopush:
        return post_rebase(stack,
                           applied,
                           'rebase',
                           check_merged=options.merged)
예제 #25
0
def func(parser, options, args):
    """Delete one or more patches."""
    stack = directory.repository.get_stack(options.branch)
    if options.branch:
        iw = None  # can't use index/workdir to manipulate another branch
    else:
        iw = stack.repository.default_iw
    if args and options.top:
        parser.error('Either --top or patches must be specified')
    elif args:
        patches = set(
            parse_patches(args, list(stack.patchorder.all),
                          len(stack.patchorder.applied)))
    elif options.top:
        applied = stack.patchorder.applied
        if applied:
            patches = set([applied[-1]])
        else:
            raise CmdException('No patches applied')
    else:
        parser.error('No patches specified')

    if options.spill:
        if set(stack.patchorder.applied[-len(patches):]) != patches:
            parser.error('Can only spill topmost applied patches')
        iw = None  # don't touch index+worktree

    return delete_patches(stack, iw, patches)
예제 #26
0
파일: mail.py 프로젝트: hasturkun/stgit
def __send_message_git(msg_bytes, from_, options):
    """Send the message using git send-email
    """
    from subprocess import call
    from tempfile import mkstemp

    cmd = ["git", "send-email", "--from=%s" % from_]
    cmd.append("--quiet")
    cmd.append("--suppress-cc=self")
    if not options.auto:
        cmd.append("--suppress-cc=body")
    if options.in_reply_to:
        cmd.extend(["--in-reply-to", options.in_reply_to])
    if options.no_thread:
        cmd.append("--no-thread")

    # We only support To/Cc/Bcc in git send-email for now.
    for x in ['to', 'cc', 'bcc']:
        if getattr(options, x):
            cmd.extend('--%s=%s' % (x, a) for a in getattr(options, x))

    (fd, path) = mkstemp()
    try:
        os.write(fd, msg_bytes)
        os.close(fd)
        try:
            cmd.append(path)
            call(cmd)
        except Exception as err:
            raise CmdException(str(err))
    finally:
        os.unlink(path)
예제 #27
0
def func(parser, options, args):
    """Pop the given patches or the topmost one from the stack."""
    stack = directory.repository.current_stack
    iw = stack.repository.default_iw
    check_head_top_equal(stack)
    if not options.keep and not options.spill:
        check_index_and_worktree_clean(stack)
    trans = transaction.StackTransaction(stack)

    if options.number == 0:
        # explicitly allow this without any warning/error message
        return

    if not trans.applied:
        raise CmdException('No patches applied')

    if options.all:
        patches = trans.applied
    elif options.number is not None:
        # reverse it twice to also work with negative or bigger than
        # the length numbers
        patches = trans.applied[::-1][:options.number][::-1]
    elif not args:
        patches = [trans.applied[-1]]
    else:
        patches = parse_patches(args, trans.applied, ordered=True)

    if not patches:
        # FIXME: Why is this an error, and not just a noop ?
        raise CmdException('No patches to pop')

    if options.spill:
        if set(stack.patchorder.applied[-len(patches):]) != set(patches):
            parser.error('Can only spill topmost applied patches')
        iw = None  # don't touch index+worktree

    try:
        trans.reorder_patches(
            applied=[p for p in trans.applied if p not in patches],
            unapplied=patches + trans.unapplied,
            iw=iw,
            allow_interactive=True,
        )
    except transaction.TransactionException:
        pass
    return trans.execute('pop', iw)
예제 #28
0
파일: new.py 프로젝트: gwd/stgit
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if stack.patches.exists(name):
            raise CmdException('%s: patch already exists' % name)
        elif not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: "%s"' % name)
    else:
        parser.error('incorrect number of arguments')

    cd = CommitData(
        tree=stack.head.data.tree,
        parents=[stack.head],
        message='',
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(cd, options)

    if options.save_template:
        options.save_template(cd.message.encode('utf-8'))
        return utils.STGIT_SUCCESS

    if not options.no_verify:
        cd = run_commit_msg_hook(stack.repository, cd)

    if name is None:
        name = utils.make_patch_name(cd.message, stack.patches.exists)
        assert stack.patches.is_name_valid(name)

    # Write the new patch.
    stack.repository.default_iw
    trans = StackTransaction(stack, 'new: %s' % name)
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.run()
예제 #29
0
def func(parser, options, args):
    """Show the patches modifying a file
    """
    if not args:
        files = [path for (stat, path) in git.tree_status(verbose=True)]
        # git.tree_status returns absolute paths
    else:
        files = git.ls_files(args)
    directory.cd_to_topdir()

    if not files:
        raise CmdException('No files specified or no local changes')

    applied = crt_series.get_applied()
    if not applied:
        raise CmdException('No patches applied')

    revs = git.modifying_revs(files, crt_series.get_base(),
                              crt_series.get_head())
    revs.reverse()

    # build the patch/revision mapping
    rev_patch = dict()
    for name in applied:
        patch = crt_series.get_patch(name)
        rev_patch[patch.get_top()] = patch

    # print the patch names
    diff_lines = []
    for rev in revs:
        patch = rev_patch[rev]
        if options.diff:
            diff_lines.extend([
                b'-' * 79,
                patch.get_name().encode('utf-8'),
                b'-' * 79,
                patch.get_description().encode('utf-8'),
                b'---',
                b'',
                git.diff(files, patch.get_bottom(), patch.get_top()),
            ])
        else:
            out.stdout(patch.get_name())

    if options.diff:
        pager(b'\n'.join(diff_lines))
예제 #30
0
def __cleanup_branch(name, force=False):
    branch = stack.Series(name)
    if branch.get_protected():
        raise CmdException(
            'This branch is protected. Clean up is not permitted')

    out.start('Cleaning up branch "%s"' % name)
    branch.delete(force=force, cleanup=True)
    out.done()