aboutsummaryrefslogtreecommitdiff
path: root/tests/unittests/testpush.py
blob: 0046e2b44fc914f13ab1af9ca5d03844c6a42bac (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import os
import unittest
import uuid

from sh import git

from linaropy.cd import cd
from linaropy.proj import Proj
from linaropy.git.clone import Clone
from linaropy.git.worktree import Worktree

from modules.llvm import get_user_from_remote, push_current_branch


class TestGetUser(unittest.TestCase):
    testdirprefix = "GetUserUT"

    def test_full_remote(self):
        user = get_user_from_remote("https://user1@remote.url:1234")
        self.assertEqual(user, "user1")

        user = get_user_from_remote("ssh://user2@remote.url:1234")
        self.assertEqual(user, "user2")

    def test_no_protocol_remote(self):
        user = get_user_from_remote("user.name@remote.url:1234")
        self.assertEqual(user, "user.name")

    def test_no_user(self):
        user = get_user_from_remote("https://remote.url:1234:")
        self.assertEqual(user, None)


class TestPush(unittest.TestCase):
    testdirprefix = "PushUT"

    def __create_dummy_commit(
            self,
            message="Branches without commits confuse git"):
        filename = "file" + str(uuid.uuid4())
        open(filename, "a").close()
        git("add", filename)
        git("commit", "-m", message)

    def __get_last_commit_message(self, branch=""):
        return str(git("rev-list", "-1", "--oneline", branch)).strip()

    def __create_dummy_repo(self, path):
        if not os.path.exists(path):
            os.makedirs(path)

        with cd(path):
            git("init")
            self.__create_dummy_commit()

    def setUp(self):
        # We're going to create a hierarchy with an origin repo, a clone repo
        # and a worktree of the clone. When pushing through the worktree, we
        # expect to see things in origin.
        self.proj = Proj(prefix=self.testdirprefix)
        self.user = "llvm-developer"

        path = os.path.join(self.proj.projdir, "origin")
        self.__create_dummy_repo(path)
        self.origin = Clone(self.proj, path)

        path = os.path.join(self.proj.projdir, "clone")
        git("clone", "file://" + self.user + "@" + self.origin.repodir, path)
        self.clone = Clone(self.proj, path)

        self.worktreeBranch = "a-branch"
        self.worktree = Worktree.create(
            self.proj, self.clone, os.path.join(
                self.proj.projdir, "worktree"), self.worktreeBranch)

    def tearDown(self):
        self.proj.cleanup()

    def test_push_new_branch(self):
        """Test that we can push a new branch to origin."""

        with cd(self.worktree.repodir):
            self.__create_dummy_commit("This should make it to origin")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(
                self.__get_last_commit_message(
                    "linaro-local/{}/{}".format(
                        self.user,
                        self.worktreeBranch)),
                ".*This should make it to origin")

    def test_push_existing_branch(self):
        """Test that we can push to a branch that already exists in origin."""

        remoteBranch = "linaro-local/{}/{}".format(
            self.user, self.worktreeBranch)

        with cd(self.worktree.repodir):
            self.__create_dummy_commit("This already exists in origin")
            git("push", "origin", "{}:{}".format(
                self.worktreeBranch, remoteBranch))

            self.__create_dummy_commit("This should make it to origin too")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(self.__get_last_commit_message(remoteBranch),
                             ".*This should make it to origin too")

    def test_push_squashed_update(self):
        """
        Test that we can push again after squashing some fixes into a commit
        that has already been pushed to origin. This isn't a nice thing to do,
        but we need to support it because Gerrit requires squashes.
        """
        remoteBranch = "linaro-local/{}/{}".format(self.user,
                                                   self.worktreeBranch)
        with cd(self.worktree.repodir):
            self.__create_dummy_commit("First version of the patch")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(
                self.__get_last_commit_message(remoteBranch),
                ".*First version of the patch")

        with cd(self.worktree.repodir):
            git("commit", "--amend", "-m", "Second version of the patch")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(
                self.__get_last_commit_message(remoteBranch),
                "/*Second version of the patch")

    def test_push_rebased_branch(self):
        """ Test that we can push again with new updates after a rebase."""
        remoteBranch = "linaro-local/{}/{}".format(self.user,
                                                   self.worktreeBranch)
        with cd(self.worktree.repodir):
            self.__create_dummy_commit("First change")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(
                self.__get_last_commit_message(remoteBranch),
                ".*First change")

        with cd(self.origin.repodir):
            self.__create_dummy_commit("Master moving forward")

        with cd(self.worktree.repodir):
            self.__create_dummy_commit("Second change")
            git("fetch", "origin", "master")
            git("rebase", "origin/master")

        push_current_branch(self.proj, self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(self.__get_last_commit_message(remoteBranch),
                             ".*Second change")

    def test_push_no_user(self):
        """Test that we error out when we can't parse a user in the remote name."""
        remote = "file://" + self.origin.repodir
        with cd(self.worktree.repodir):
            git("remote", "set-url", "origin", remote)
            self.__create_dummy_commit("Make it look like a real branch")

        with self.assertRaises(EnvironmentError) as context:
            push_current_branch(self.proj, self.worktree.repodir)

        self.assertEqual(str(context.exception),
                         "Couldn't parse user from {}.".format(remote))

    def test_push_invalid_user(self):
        """Test that we error out when the value of LLVM_GITUSER wouldn't look good in a branch name (e.g. if it contains spaces)."""

        badUser = "LLVM Developer"
        with cd(self.worktree.repodir):
            git("remote", "set-url", "origin",
                "file://{}@{}".format(badUser, self.origin.repodir))
            self.__create_dummy_commit("Make it look like a real branch")

        with self.assertRaises(EnvironmentError) as context:
            push_current_branch(self.proj, self.worktree.repodir)

        self.assertEqual(str(context.exception),
                         "linaro-local/{}/{} is not a valid branch name.".format(badUser,
                                                                                 self.worktreeBranch))

if __name__ == "__main__":
    unittest.main()