aboutsummaryrefslogtreecommitdiff
path: root/modules/utils.py
blob: c76b3fb8cd9fff31ab502d6afd50ad1ad6febbfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from subprocess import PIPE
from subprocess import Popen
from subprocess import STDOUT
from subprocess import SubprocessError

import re

from linaropy.git.worktree import Worktree


class CommandPrinter(object):
    """Command consumer that just prints the commands that it receives."""

    def consume(self, command, directory):
        print("{}$ {}".format(directory, ' '.join(command)))


class CommandRunner(object):
    """Command consumer that runs the commands that it receives."""

    def consume(self, command, directory):
        """
        Run the given command in the given directory and print the stdout and
        stderr. If 'directory' is None, the current working directory is used.
        If an exception is thrown while running the command, it will be rethrown
        as a RuntimeError.
        """
        try:
            with Popen(command, stdout=PIPE, stderr=STDOUT, cwd=directory) as process:
                for line in process.stdout:
                    print(str(line, 'utf-8'), end='')
            if process.returncode != 0:
                raise RuntimeError(
                    "Command failed with return code: {}\n".format(
                        process.returncode))
        except SubprocessError as exc:
            raise RuntimeError(
                "Error while running command\n{}".format(str(exc.output, 'utf-8'))) from exc


# FIXME: repo.pushToBranch doesn't work, because it doesn't handle remote
# branches properly. Furthermore, there's no support for getting the remote URL,
# so we need to resort to raw git commands. We may also consider moving the
# functionality for parsing info out of the remote URL into the repo object.
from sh import git
from linaropy.cd import cd


def get_user_from_remote(url):
    """Get the username used as part of the remote URL, or None.

    The remote URLs that we expect to see look like $protocol://$user@$location.
    If they look any different, we won't be able to parse them.
    """
    pattern = re.compile("(.*://)?(?P<user>.*)@(.*)\n?")
    match = pattern.match(str(url))
    if match is None:
        return None
    return match.group('user')


def get_remote_branch(repo, local_branch):
    """
    Get the name of the remote branch corresponding to the given local branch.
    """
    with cd(repo.repodir):
        remote = git("remote", "get-url", "--push", "origin").strip()
    user = get_user_from_remote(remote)
    if not user:
        raise EnvironmentError("Couldn't parse user from {}.".format(remote))

    remote_branch = "linaro-local/{}/{}".format(user, local_branch)
    if not repo.is_valid_branch_name(remote_branch):
        raise EnvironmentError(
            "{} is not a valid branch name.".format(remote_branch))

    return remote_branch


def push_branch(proj, local_branch, remote_branch, pathToRepo):
    """Push the given local branch into origin's given remote branch."""
    repo = Worktree(proj, pathToRepo)
    with cd(repo.repodir):
        git("push", "-u", "origin", "+{}:{}".format(local_branch, remote_branch))