aboutsummaryrefslogtreecommitdiff
path: root/tests/unittests/testpush.py
blob: 3eb8e355c37a4a183ceba26d49bee1d0f50009a4 (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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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, get_remote_branch, push_branch

# FIXME: Maybe move these helpers somewhere more public, or use LLVMTestCase for
# these tests as well...


def create_dummy_commit(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(branch=""):
    return str(git("rev-list", "-1", "--oneline", branch)).strip()


def create_dummy_repo(path):
    if not os.path.exists(path):
        os.makedirs(path)

    with cd(path):
        git("init")
        create_dummy_commit()


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 TestGetRemoteBranch(unittest.TestCase):
    testdirprefix = "GetRemoteBranchUT"

    def setUp(self):
        # Create a git repo so we can play with its remotes.
        self.proj = Proj(prefix=self.testdirprefix)

        path = os.path.join(self.proj.projdir, "repo")
        create_dummy_repo(path)
        self.repo = Clone(self.proj, path)

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

    def test_valid_branch(self):
        """
        Test that we return the correct remote branch name if everything is
        valid.
        """
        user = "a.user"
        remote = "file://{}@{}".format(user, self.repo.repodir)
        with cd(self.repo.repodir):
            git("remote", "add", "origin", remote)

        local_branch = "a-branch"
        remote_branch = get_remote_branch(self.repo, local_branch)
        self.assertEqual(
            remote_branch, "linaro-local/{}/{}".format(user, local_branch))

    def test_no_user(self):
        """Test that we error out when we can't parse a user in the remote name."""
        remote = "file://" + self.repo.repodir
        with cd(self.repo.repodir):
            git("remote", "add", "origin", remote)

        with self.assertRaises(EnvironmentError) as context:
            get_remote_branch(self.repo, "a-branch")

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

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

        badUser = "LLVM Developer"
        with cd(self.repo.repodir):
            git("remote", "add", "origin",
                "file://{}@{}".format(badUser, self.repo.repodir))

        branch = "a-branch"
        with self.assertRaises(EnvironmentError) as context:
            get_remote_branch(self.repo, branch)

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


class TestPushBranch(unittest.TestCase):
    testdirprefix = "PushBranchUT"

    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")
        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.remoteBranch = "remotely/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):
            create_dummy_commit("This should make it to origin")

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(
                get_last_commit_message(self.remoteBranch),
                ".*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."""
        with cd(self.worktree.repodir):
            create_dummy_commit("This already exists in origin")
            git("push", "origin", "{}:{}".format(
                self.worktreeBranch, self.remoteBranch))

            create_dummy_commit("This should make it to origin too")

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

        with cd(self.origin.repodir):
            self.assertRegex(get_last_commit_message(self.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.
        """
        with cd(self.worktree.repodir):
            create_dummy_commit("First version of the patch")

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

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

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

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

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

    def test_push_rebased_branch(self):
        """ Test that we can push again with new updates after a rebase."""
        with cd(self.worktree.repodir):
            create_dummy_commit("First change")

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

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

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

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

        push_branch(self.proj, self.worktreeBranch, self.remoteBranch,
                    self.worktree.repodir)

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

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