Exemple #1
0
    def test_push_tag_using_branch_reference_name(self):
        """Try pushing a tag as if it was a branch.

        Excercise the scenario where a user is trying to push a tag
        using a reference whose name indicates that this is a branch.
        This is a bit far-fetched in most cases, but might be less so
        in repositories that start using their own naming scheme.
        We want to make sure we handle these situations gracefullly
        in any case.
        """
        cd('%s/repo' % TEST_DIR)

        # Push refs/tags/v1, which is a tag, to a reference whose name
        # suggests it is a branch. We should get an error.
        p = Run('git push origin refs/tags/v1:refs/heads/v1'.split())
        expected_out = """\
remote: *** This type of update (refs/heads/v1,tag) is not valid.
remote: error: hook declined to update refs/heads/v1
To ../bare/repo.git
 ! [remote rejected] v1 -> v1 (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #2
0
    def test_delete_branch_with_std_name(self):
        """Push a branch deletion using a standard reference name."""
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin :to-delete'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Deleted branch 'to-delete'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/heads/to-delete
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 0000000000000000000000000000000000000000
remote:
remote: The branch 'to-delete' was deleted.
remote: It previously pointed to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 - [deleted]         to-delete
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #3
0
    def test_create_branch_custom_name_recognized(self):
        """Create a new branch with a custom reference name.

        This reference name is recognized as a branch by the repository's
        naming scheme.
        """
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin master:refs/vendor/name/topic'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Created branch 'name/topic' in namespace 'refs/vendor'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/vendor/name/topic
remote: X-Git-Oldrev: 0000000000000000000000000000000000000000
remote: X-Git-Newrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote:
remote: The branch 'name/topic' was created in namespace 'refs/vendor' pointing to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 * [new branch]      master -> refs/vendor/name/topic
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #4
0
    def test_create_branch_with_standard_name(self):
        """Create a new branch with a standard reference name.
        """
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin master:new-master'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Created branch 'new-master'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/heads/new-master
remote: X-Git-Oldrev: 0000000000000000000000000000000000000000
remote: X-Git-Newrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote:
remote: The branch 'new-master' was created pointing to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 * [new branch]      master -> new-master
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #5
0
    def test_delete_nonexistant(self):
        """Try deleting a references that don't exist on the remote."""
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin :does-not-exist'.split())
        expected_out = """\
error: unable to delete 'does-not-exist': remote ref does not exist
error: failed to push some refs to '../bare/repo.git'
"""
        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Do the same as above, but using the full reference, instead
        # of using the branch name.

        p = Run('git push origin :refs/heads/does-not-exist'.split())
        expected_out = """\
remote: *** unable to delete 'refs/heads/does-not-exist': remote ref does not exist
remote: error: hook declined to update refs/heads/does-not-exist
To ../bare/repo.git
 ! [remote rejected] does-not-exist (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""
        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Same as above, but using the full reference in the tags
        # namespace.

        p = Run('git push origin :refs/tags/does-not-exist'.split())
        expected_out = """\
remote: *** unable to delete 'refs/tags/does-not-exist': remote ref does not exist
remote: error: hook declined to update refs/tags/does-not-exist
To ../bare/repo.git
 ! [remote rejected] does-not-exist (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""
        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Same as above, but using the full reference in the notes
        # namespace.

        p = Run('git push origin :refs/notes/commits'.split())
        expected_out = """\
remote: *** unable to delete 'refs/notes/commits': remote ref does not exist
remote: error: hook declined to update refs/notes/commits
To ../bare/repo.git
 ! [remote rejected] refs/notes/commits (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""
        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #6
0
    def test_delete_branch_custom_name_recognized(self):
        """Push a branch deletion using a custom reference name."""
        cd('%s/repo' % TEST_DIR)

        # Try to delete a branch with a custom name which does exist
        # in the remote repository, and is recognized by the naming
        # scheme as a branch. This should be accepted.
        p = Run('git push origin :refs/user/to-delete'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Deleted branch 'to-delete' in namespace 'refs/user'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/user/to-delete
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 0000000000000000000000000000000000000000
remote:
remote: The branch 'to-delete' in namespace 'refs/user' was deleted.
remote: It previously pointed to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 - [deleted]         refs/user/to-delete
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Try to delete a branch with a reference name which is
        # recognized by the naming scheme as a branch, but does not
        # exist in the remote repository. This will obviously fail.
        p = Run('git push origin :refs/user/does-not-exist'.split())
        expected_out = """\
remote: *** unable to delete 'refs/user/does-not-exist': remote ref does not exist
remote: error: hook declined to update refs/user/does-not-exist
To ../bare/repo.git
 ! [remote rejected] refs/user/does-not-exist (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #7
0
    def test_update_branch_custom_name_recognized(self):
        """Push a branch update using a custom reference name."""
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin my-topic:refs/user/myself/my-feature'.split())
        expected_out = """\
remote: *** cvs_check: `repo' < `a'
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo(refs/user/myself/my-feature)] update a to add terminator line
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/user/myself/my-feature
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 2a112bb1c30346f6287bb3d5c157a93235ea861f
remote:
remote: commit 2a112bb1c30346f6287bb3d5c157a93235ea861f
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Mar 1 20:15:13 2020 +0400
remote:
remote:     update a to add terminator line
remote:
remote: Diff:
remote: ---
remote:  a | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/a b/a
remote: index 01d0f12..698778b 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1,3 +1,4 @@
remote:  Some file.
remote:  Second line.
remote:  Third line.
remote: +Terminator.
To ../bare/repo.git
   d065089..2a112bb  my-topic -> refs/user/myself/my-feature
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #8
0
    def test_delete_branch_with_std_name(self):
        """Push a branch deletion using a standard reference name."""
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin :to-delete'.split())
        expected_out = """\
remote: *** Deleting branches is not allowed for this repository.
remote: ***
remote: *** If you are trying to delete a branch which was created
remote: *** by accident, then please contact your favorite admin
remote: *** and he will take care of removing the branch for you.
remote: error: hook declined to update refs/heads/to-delete
To ../bare/repo.git
 ! [remote rejected] to-delete (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #9
0
    def test_create_branch_custom_name_not_recognized(self):
        """Create a new branch with a custom reference name.

        This reference name is not recognized as a branch by
        the repository's naming scheme, and so the update should
        be rejected.
        """
        cd('%s/repo' % TEST_DIR)

        p = Run(
            'git push origin master:refs/does-not-exist/my-feature'.split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/does-not-exist/my-feature
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/.*
remote: ***       refs/meta/.*
remote: ***       refs/drafts/.*
remote: ***       refs/for/.*
remote: ***       refs/publish/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/does-not-exist/my-feature
To ../bare/repo.git
 ! [remote rejected] master -> refs/does-not-exist/my-feature (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #10
0
    def test_delete_branch_with_std_name(self):
        """Push a branch deletion using a standard reference name."""
        cd('%s/repo' % TEST_DIR)

        p = Run('git push origin :to-delete'.split())
        expected_out = """\
remote: *** Deleting branches is not allowed for this repository.
remote: ***
remote: *** If you are trying to delete a branch which was created
remote: *** by mistake, contact an administrator, and ask him to
remote: *** temporarily change the repository's configuration
remote: *** so the branch can be deleted (he may elect to delete
remote: *** the branch himself to avoid the need to coordinate
remote: *** the operation).
remote: error: hook declined to update refs/heads/to-delete
To ../bare/repo.git
 ! [remote rejected] to-delete (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #11
0
    def test_commit_commit_email_formatter(self):
        """Test the hooks.commit-email-formatter hook.

        The purpose of this testcase is to perform a sanity check
        of the behavior of the git-hooks when a user pushes some changes
        to a repository where the hooks.commit-email-formatter config
        option is set.

        The script we use for that is called commit-email-formatter.py,
        and was written to facilitate testing of the various possible
        scenarios we want to support with this commit-email-formatter
        hook. It does so by inspecting the various commits and react
        differently based on the commit (generally speaking, it takes
        cues from the commit's revision log).
        """
        cd('%s/repo' % TEST_DIR)

        # First, update the git-hooks configuration to install our
        # the script we want to use as our commit-email-formatter.

        p = Run(['git', 'fetch', 'origin', 'refs/meta/config'])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'checkout', 'FETCH_HEAD'])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'config', '--file', 'project.config',
                 'hooks.commit-email-formatter',
                 os.path.join(TEST_DIR, 'commit-email-formatter.py')])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'commit', '-m', 'Add hooks.commit-email-formatter',
                 'project.config'])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'push', 'origin', 'HEAD:refs/meta/config'])
        self.assertEqual(p.status, 0, p.image)
        # Check the last line that git printed, and verify that we have
        # another piece of evidence that the change was succesfully pushed.
        self.assertTrue('HEAD -> refs/meta/config' in p.out.splitlines()[-1],
                        p.image)

        # Return our current HEAD to branch "master". Not critical for
        # our testing, but it helps the testcase be closer to the more
        # typical scenarios.
        p = Run(['git', 'checkout', 'master'])
        self.assertEqual(p.status, 0, p.image)

        # Push the "master" branch, which introduces a series of commits.
        # Each commit will be handled by our commit-email-formatter.py
        # script based on its contents, with the commits being created
        # so as to help us cover the whole range of options we support.
        # This makes for a fairly long list of commits, which means
        # a correspondingly long output. We are testing it this way
        # (one push of multiple commits) so as to verify that unexpected
        # behavior of the commit-email-formatter hook doesn't affect
        # the next commit.

        p = Run('git push origin master'.split())

        # Let's split the expected_out by commits, so we can add comments
        # describing each commit prior to being processed by our hook.
        expected_out = ""

        # | commit 433a74237b4d8849da6bd33f6cfdda1919086358
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 10:27:19 2020 -0700
        # |
        # |     Add "Introduction" section title
        #
        # We expected the subject and email body to be customized.
        # We should also see a "diff" section, even though the hook
        # didn't provide a value for "diff". This verifies that
        # we handle the default properly.

        expected_out += """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: New subject: Add intro
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: bb7753f79d9fbab15012afb1d8214ed0fec0a00d
remote: X-Git-Newrev: 433a74237b4d8849da6bd33f6cfdda1919086358
remote:
remote: My customized email body
remote: (with diff)
remote:
remote: Diff:
remote: ---
remote:  a | 3 +++
remote:  1 file changed, 3 insertions(+)
remote:
remote: diff --git a/a b/a
remote: index 18832d3..286976e 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1 +1,4 @@
remote: +Introduction
remote: +============
remote: +
remote:  Hello.
"""

        # | commit 5fee44f6ec23bde253ac8e4a80fb10c5b7469e48
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 10:34:59 2020 -0700
        # |
        # |     Improve introduction
        #
        # We expect the subject to be customized, and the rest should be
        # the same as the default commit email.

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: New subject:Improve introduction
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 433a74237b4d8849da6bd33f6cfdda1919086358
remote: X-Git-Newrev: 5fee44f6ec23bde253ac8e4a80fb10c5b7469e48
remote:
remote: commit 5fee44f6ec23bde253ac8e4a80fb10c5b7469e48
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 10:34:59 2020 -0700
remote:
remote:     Improve introduction
remote:
remote: Diff:
remote: ---
remote:  a | 2 +-
remote:  1 file changed, 1 insertion(+), 1 deletion(-)
remote:
remote: diff --git a/a b/a
remote: index 286976e..a7cd38e 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1,4 +1,4 @@
remote:  Introduction
remote:  ============
remote:
remote: -Hello.
remote: +Hello. This is going to be a useful document.
"""

        # | commit 3a81561f42669f8ae85304a67ca30225afe780f9
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 10:36:43 2020 -0700
        # |
        # |     Add new file: b
        #
        # The email body should be customized, and the "Diff: section should
        # be absent (because the hook returned "diff" set to None).

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Add new file: b
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 5fee44f6ec23bde253ac8e4a80fb10c5b7469e48
remote: X-Git-Newrev: 3a81561f42669f8ae85304a67ca30225afe780f9
remote:
remote: New Body
remote:
remote: [Diff removed for reason X and Y]
"""

        # | commit 83b7d3bc13428241abb3f27aad2e226c809e5e56
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:31:49 2020 -0700
        # |
        # |     Update b
        # |
        # |     (no-diff-in-email)
        #
        # We expect the email to be the same as the default email,
        # except that the "diff" section has been removed.
        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Update b
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 3a81561f42669f8ae85304a67ca30225afe780f9
remote: X-Git-Newrev: 83b7d3bc13428241abb3f27aad2e226c809e5e56
remote:
remote: commit 83b7d3bc13428241abb3f27aad2e226c809e5e56
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:31:49 2020 -0700
remote:
remote:     Update b
remote:
remote:     (no-diff-in-email)
remote:
"""

        # | commit 6b65d08866b52c750df5ace3f18357133e352b4e
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:34:01 2020 -0700
        # |
        # |     Update a
        #
        # A commit with nothing in particular. The hook should return
        # an empty dict, signifying that nothing should be customized
        # (meaning, the standard email should get sent).
        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Update a
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 83b7d3bc13428241abb3f27aad2e226c809e5e56
remote: X-Git-Newrev: 6b65d08866b52c750df5ace3f18357133e352b4e
remote:
remote: commit 6b65d08866b52c750df5ace3f18357133e352b4e
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:34:01 2020 -0700
remote:
remote:     Update a
remote:
remote: Diff:
remote: ---
remote:  a | 2 +-
remote:  1 file changed, 1 insertion(+), 1 deletion(-)
remote:
remote: diff --git a/a b/a
remote: index a7cd38e..579abc9 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1,4 +1,4 @@
remote:  Introduction
remote:  ============
remote:
remote: -Hello. This is going to be a useful document.
remote: +Hello. This is going to be a useful document for everyone to read.
"""

        # | commit 4131b4399e258bd3c36119d026455a4abce2e971
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:37:44 2020 -0700
        # |
        # |     Improve b (email-formatter:return-nonzero)
        #
        # This commit will cause the hook to return nonzero.
        #
        # In that situation, the git-hooks are expected to fall back
        # to the default commit email, with a warning at the end of
        # the email body (but before the diff).

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Improve b (email-formatter:return-nonzero)
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 6b65d08866b52c750df5ace3f18357133e352b4e
remote: X-Git-Newrev: 4131b4399e258bd3c36119d026455a4abce2e971
remote:
remote: commit 4131b4399e258bd3c36119d026455a4abce2e971
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:37:44 2020 -0700
remote:
remote:     Improve b (email-formatter:return-nonzero)
remote:
remote: | WARNING:
remote: | hooks.commit-email-formatter returned nonzero: 1.
remote: | Falling back to default email format.
remote: |
remote: | $ {TEST_DIR}/commit-email-formatter.py refs/heads/master 4131b4399e258bd3c36119d026455a4abce2e971
remote: | Something went wrong, ouh la la, this is me crashing, no good!
remote: |
remote:
remote: Diff:
remote: ---
remote:  b | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/b b/b
remote: index 3639688..cc5e45c 100644
remote: --- a/b
remote: +++ b/b
remote: @@ -1 +1,2 @@
remote:  New file with some interesting contents.
remote: +Let's start with some background: dark.
""".format(TEST_DIR=TEST_DIR)

        # | commit 3d75bd9d3a551d8b66b8ec7b79eedc7496bb804f
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:40:46 2020 -0700
        # |
        # |     Improve introduction once more
        #
        # A commit for which no error is expected, to verify that
        # the error handling in the previous commit does not affect
        # the handling of this commit.
        #
        # The subject is set up so as to "trigger" commit-email-formatter.py
        # to customize the subject and force the diff (which was the default
        # anyway).

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: New subject:Improve introduction once more
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 4131b4399e258bd3c36119d026455a4abce2e971
remote: X-Git-Newrev: 3d75bd9d3a551d8b66b8ec7b79eedc7496bb804f
remote:
remote: commit 3d75bd9d3a551d8b66b8ec7b79eedc7496bb804f
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:40:46 2020 -0700
remote:
remote:     Improve introduction once more
remote:
remote: Diff:
remote: ---
remote:  a | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/a b/a
remote: index 579abc9..3ef8ed1 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -2,3 +2,4 @@ Introduction
remote:  ============
remote:
remote:  Hello. This is going to be a useful document for everyone to read.
remote: +It will provide detailed information on this thing.
"""

        # | commit ee3e1d03e6decce59fce06f3a2fe256f0221cb80
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:42:05 2020 -0700
        # |
        # |     continue improving B (email-formatter:return-bad-json)
        #
        # This commit will cause the hook to return some output which
        # is not valid JSON.
        #
        # In that situation, the git-hooks are expected to fall back
        # to the default commit email, with a warning at the end of
        # the email body (but before the diff).
        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] continue improving B (email-formatter:return-bad-json)
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: 3d75bd9d3a551d8b66b8ec7b79eedc7496bb804f
remote: X-Git-Newrev: ee3e1d03e6decce59fce06f3a2fe256f0221cb80
remote:
remote: commit ee3e1d03e6decce59fce06f3a2fe256f0221cb80
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:42:05 2020 -0700
remote:
remote:     continue improving B (email-formatter:return-bad-json)
remote:
remote: | WARNING:
remote: | hooks.commit-email-formatter returned invalid JSON.
remote: | Falling back to default email format.
remote: |
remote: | $ {TEST_DIR}/commit-email-formatter.py refs/heads/master ee3e1d03e6decce59fce06f3a2fe256f0221cb80
remote: | {{
remote: |
remote:
remote: Diff:
remote: ---
remote:  b | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/b b/b
remote: index cc5e45c..f20781f 100644
remote: --- a/b
remote: +++ b/b
remote: @@ -1,2 +1,3 @@
remote:  New file with some interesting contents.
remote:  Let's start with some background: dark.
remote: +Let's then look at the foreground: Bright colorful.
""".format(TEST_DIR=TEST_DIR)

        # | commit e617216033a96c18bad5b2235d960c784dd3efa7
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:46:51 2020 -0700
        # |
        # |     more information in b.
        # |
        # |     (no-diff-in-email)
        #
        # A commit for which no error is expected, to verify that
        # the error handling in the previous commit does not affect
        # the handling of this commit.
        #
        # The email should be as per the default, except that the "Diff:"
        # section is omitted.

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] more information in b.
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: ee3e1d03e6decce59fce06f3a2fe256f0221cb80
remote: X-Git-Newrev: e617216033a96c18bad5b2235d960c784dd3efa7
remote:
remote: commit e617216033a96c18bad5b2235d960c784dd3efa7
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:46:51 2020 -0700
remote:
remote:     more information in b.
remote:
remote:     (no-diff-in-email)
remote:
"""

        # | commit c47a7f0a65557eb1551b5fd80e753d81c529c69a
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:49:14 2020 -0700
        # |
        # |     More [snip snip] (email-formatter:return-not-dict)
        #
        # This commit will cause the hook to return nonzero.
        #
        # In that situation, the git-hooks are expected to fall back
        # to the default commit email, with a warning at the end of
        # the email body (but before the diff).

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] More text in a's introduction section
remote:  (email-formatter:return-not-dict)
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: e617216033a96c18bad5b2235d960c784dd3efa7
remote: X-Git-Newrev: c47a7f0a65557eb1551b5fd80e753d81c529c69a
remote:
remote: commit c47a7f0a65557eb1551b5fd80e753d81c529c69a
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:49:14 2020 -0700
remote:
remote:     More text in a's introduction section (email-formatter:return-not-dict)
remote:
remote: | WARNING:
remote: | hooks.commit-email-formatter output is not JSON dict.
remote: | Falling back to default email format.
remote: |
remote: | $ {TEST_DIR}/commit-email-formatter.py refs/heads/master c47a7f0a65557eb1551b5fd80e753d81c529c69a
remote: | [1, 2, 3]
remote: |
remote:
remote: Diff:
remote: ---
remote:  a | 3 ++-
remote:  1 file changed, 2 insertions(+), 1 deletion(-)
remote:
remote: diff --git a/a b/a
remote: index 3ef8ed1..5a94736 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -2,4 +2,5 @@ Introduction
remote:  ============
remote:
remote:  Hello. This is going to be a useful document for everyone to read.
remote: -It will provide detailed information on this thing.
remote: +It will provide detailed information on this thing, including
remote: +information that you might never have thought about.
""".format(TEST_DIR=TEST_DIR)

        # | commit 699356fb0903efbe73a18e2573a9ca67bc7c35a5 (HEAD -> master)
        # | Author: Joel Brobecker <*****@*****.**>
        # | Date:   Sun Aug 2 14:52:44 2020 -0700
        # |
        # |     Provide information about the sky (no-diff-in-email)
        #
        # A commit for which no error is expected, to verify that
        # the error handling in the previous commit does not affect
        # the handling of this commit.
        #
        # The email should be as per the default, except that the "diff"
        # section is omitted.

        expected_out += """\
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Provide information about the sky (no-diff-in-email)
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: c47a7f0a65557eb1551b5fd80e753d81c529c69a
remote: X-Git-Newrev: 699356fb0903efbe73a18e2573a9ca67bc7c35a5
remote:
remote: commit 699356fb0903efbe73a18e2573a9ca67bc7c35a5
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Aug 2 14:52:44 2020 -0700
remote:
remote:     Provide information about the sky (no-diff-in-email)
remote:
To ../bare/repo.git
   bb7753f..699356f  master -> master
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Now, push branch "hook-dump", which has a single commit
        # whose subject is such that commit-email-formatter.py will
        # know to replace the email's body with the data it was given
        # via stdin. While at it, it also exercises the replacement
        # of the "Diff:" section.

        p = Run('git push origin hook-dump'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Created branch 'hook-dump'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/heads/hook-dump
remote: X-Git-Oldrev: 0000000000000000000000000000000000000000
remote: X-Git-Newrev: c7642aaf521a65fcd2414d1b9e51f7d51b881370
remote:
remote: The branch 'hook-dump' was created pointing to:
remote:
remote:  c7642aa... Update a (dump_hook_data).
remote: DEBUG: inter-email delay...
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo/hook-dump] Update a (dump_hook_data).
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/hook-dump
remote: X-Git-Oldrev: bb7753f79d9fbab15012afb1d8214ed0fec0a00d
remote: X-Git-Newrev: c7642aaf521a65fcd2414d1b9e51f7d51b881370
remote:
remote: * author_email: [email protected]
remote: * author_name: Joel Brobecker
remote: * body: Update a (dump_hook_data).
remote: * email_default_body: <multiline>
remote:    | commit c7642aaf521a65fcd2414d1b9e51f7d51b881370
remote:    | Author: Joel Brobecker <*****@*****.**>
remote:    | Date:   Sun Aug 2 18:26:31 2020 -0700
remote:    |
remote:    |     Update a (dump_hook_data).
remote:
remote: * email_default_diff: <multiline>
remote:    | ---
remote:    |  a | 2 +-
remote:    |  1 file changed, 1 insertion(+), 1 deletion(-)
remote:    |
remote:    | diff --git a/a b/a
remote:    | index 18832d3..c12abce 100644
remote:    | --- a/a
remote:    | +++ b/a
remote:    | @@ -1 +1 @@
remote:    | -Hello.
remote:    | +Hello there.
remote: * email_default_subject: [repo/hook-dump] Update a (dump_hook_data).
remote: * object_type: commit
remote: * ref_kind: branch
remote: * ref_name: refs/heads/hook-dump
remote: * rev: c7642aaf521a65fcd2414d1b9e51f7d51b881370
remote: * subject: Update a (dump_hook_data).
remote: Diff:
remote: [Diff suppressed for reason X or Y]
To ../bare/repo.git
 * [new branch]      hook-dump -> hook-dump
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a notes commit.
        #
        # Our commit-email-formatter.py script is expected to notice that
        # this is a notes commit, and customize the email's subject and
        # body (dumping the data given to the script), as well as suppress
        # the diff.

        p = Run('git push origin notes/commits'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: Customized notes email subject
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/notes/commits
remote: X-Git-Oldrev:
remote: X-Git-Newrev: 91dd8e566584e81b1d6cd69fed5aa0b34e8ede3a
remote:
remote: * author_email: [email protected]
remote: * author_name: Joel Brobecker
remote: * body: Notes added by 'git notes add'
remote: * email_default_body: <multiline>
remote:    | A Git note has been updated; it now contains:
remote:    |
remote:    |     Provide information missing from this commit's revision log (notes-commit)
remote:    |
remote:    | This note annotates the following commit:
remote:    |
remote:    | commit 699356fb0903efbe73a18e2573a9ca67bc7c35a5
remote:    | Author: Joel Brobecker <*****@*****.**>
remote:    | Date:   Sun Aug 2 14:52:44 2020 -0700
remote:    |
remote:    |     Provide information about the sky (no-diff-in-email)
remote:
remote: * email_default_diff: <multiline>
remote:    |
remote:    | diff --git a/699356fb0903efbe73a18e2573a9ca67bc7c35a5 b/699356fb0903efbe73a18e2573a9ca67bc7c35a5
remote:    | new file mode 100644
remote:    | index 0000000..6314b20
remote:    | --- /dev/null
remote:    | +++ b/699356fb0903efbe73a18e2573a9ca67bc7c35a5
remote:    | @@ -0,0 +1 @@
remote:    | +Provide information missing from this commit's revision log (notes-commit)
remote: * email_default_subject: [notes][repo] Provide information about the sky (no-diff-in-email)
remote: * object_type: commit
remote: * ref_kind: notes
remote: * ref_name: refs/notes/commits
remote: * rev: 91dd8e566584e81b1d6cd69fed5aa0b34e8ede3a
remote: * subject: Notes added by 'git notes add'
To ../bare/repo.git
 * [new branch]      refs/notes/commits -> refs/notes/commits
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #12
0
    def test_commit_checker_hook_on_branches(self):
        """Test pushing branch updates with a commit-extra-checker.

        The purpose of this testcase is to perform a sanity-check
        of the various branch push scenarios for repositories whose
        git-hooks configuration define hooks.commit-extra-checker.
        The main objective is to verify that this hook is called
        when expected, and only when expected, and that the hooks
        handle its return value correctly.

        The script we use for that is called commit-extra-checker.py,
        and was written to facilitate...
          - verification: It simply dumps on standard output the scripts
            arguments and data passed via stdin;
          - testing: It passes all commits unless it finds the string
            "(bad-commit)" somewhere in the stdin data given. That way,
            for commits we want the script to reject, we add that string
            to the commit's revision log.
        """
        cd('%s/repo' % TEST_DIR)

        # In this testcase, the contents of the emails being sent
        # by the git-hooks is not important, so reduce verbosity at
        # that level to reduce the noise in the hooks' output.

        self.change_email_sending_verbosity(full_verbosity=False)

        # First, update the git-hooks configuration to install our
        # the script we want to use as our commit-extra-checker.

        p = Run(['git', 'fetch', 'origin', 'refs/meta/config'])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'checkout', 'FETCH_HEAD'])
        self.assertEqual(p.status, 0, p.image)

        p = Run([
            'git', 'config', '--file', 'project.config',
            'hooks.commit-extra-checker',
            os.path.join(TEST_DIR, 'commit-extra-checker.py')
        ])
        self.assertEqual(p.status, 0, p.image)

        p = Run([
            'git', 'commit', '-m', 'Add hooks.commit-extra-checker',
            'project.config'
        ])
        self.assertEqual(p.status, 0, p.image)

        p = Run(['git', 'push', 'origin', 'HEAD:refs/meta/config'])
        self.assertEqual(p.status, 0, p.image)
        # Check the last line that git printed, and verify that we have
        # another piece of evidence that the change was succesfully pushed.
        self.assertTrue('HEAD -> refs/meta/config' in p.out.splitlines()[-1],
                        p.image)

        # While at it, verify that the commit-extra-checker was called
        # to check that commit. Our hooks generates some output so
        # look for that.
        self.assertTrue('DEBUG: commit-extra-checker.py' in p.out, p.image)

        # Push a branch which introduces a single new commit, which
        # we expect the commit-extra-checker to accept the commit.

        p = Run('git push origin single-commit-accept'.split())
        expected_out = """\
remote: DEBUG: commit-extra-checker.py refs/heads/single-commit-accept f109361240e74d710e8e7927495104ab40943060
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "This is an ok commit touching file a.", "author_email": "*****@*****.**", "subject": "This is an ok commit touching file a.", "object_type": "commit", "rev": "f109361240e74d710e8e7927495104ab40943060", "author_name": "Joel Brobecker", "ref_name": "refs/heads/single-commit-accept"}
remote: ---[ end stdin ]---
remote: DEBUG: Sending email: [repo/single-commit-accept] This is an ok commit touching file a....
To ../bare/repo.git
   1e1e706..f109361  single-commit-accept -> single-commit-accept
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch which introduces a single new commit,
        # which we expect the commit-extra-checker to reject.

        p = Run('git push origin single-commit-reject'.split())
        expected_out = """\
remote: *** The following commit was rejected by your hooks.commit-extra-checker script (status: 1)
remote: *** commit: 2c27994b8413d8b9515ebd38a0b229639809e5c1
remote: *** DEBUG: commit-extra-checker.py refs/heads/single-commit-reject 2c27994b8413d8b9515ebd38a0b229639809e5c1
remote: *** -----[ stdin ]-----
remote: *** {"ref_kind": "branch", "body": "modify a with some contents (bad-commit)", "author_email": "*****@*****.**", "subject": "modify a with some contents (bad-commit)", "object_type": "commit", "rev": "2c27994b8413d8b9515ebd38a0b229639809e5c1", "author_name": "Joel Brobecker", "ref_name": "refs/heads/single-commit-reject"}
remote: *** ---[ end stdin ]---
remote: *** Error: Invalid bla bla bla. Rejecting Update.
remote: error: hook declined to update refs/heads/single-commit-reject
To ../bare/repo.git
 ! [remote rejected] single-commit-reject -> single-commit-reject (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch which introduces more than one new commit,
        # which we expect the commit-extra-checker to accept.
        #
        # This push updates the branch with 3 new commits, and the 3 commits
        # are completely new for the repository, meaning that the commits
        # haven't already been pushed via other branches. As a result of
        # these commits being completely new, the commit-extra-checker
        # is expected to be called for each and every of these 3 commits.

        p = Run('git push origin multiple-commits-accept-all-new'.split())
        expected_out = """\
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-accept-all-new 4a250d3fd87947c594579e14b5688d1e60514883
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Add b", "author_email": "*****@*****.**", "subject": "Add b", "object_type": "commit", "rev": "4a250d3fd87947c594579e14b5688d1e60514883", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-accept-all-new"}
remote: ---[ end stdin ]---
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-accept-all-new 97ce4ee0f0bbb3a56c5075b9037f4caf1ce5047f
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Add c", "author_email": "*****@*****.**", "subject": "Add c", "object_type": "commit", "rev": "97ce4ee0f0bbb3a56c5075b9037f4caf1ce5047f", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-accept-all-new"}
remote: ---[ end stdin ]---
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-accept-all-new 309196cc8cf49451d8030e4c25013f3791f6a946
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Remove a (not needed anymore)", "author_email": "*****@*****.**", "subject": "Remove a (not needed anymore)", "object_type": "commit", "rev": "309196cc8cf49451d8030e4c25013f3791f6a946", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-accept-all-new"}
remote: ---[ end stdin ]---
remote: DEBUG: Sending email: [repo/multiple-commits-accept-all-new] Add b...
remote: DEBUG: inter-email delay...
remote: DEBUG: Sending email: [repo/multiple-commits-accept-all-new] Add c...
remote: DEBUG: inter-email delay...
remote: DEBUG: Sending email: [repo/multiple-commits-accept-all-new] Remove a (not needed anymore)...
To ../bare/repo.git
   1e1e706..309196c  multiple-commits-accept-all-new -> multiple-commits-accept-all-new
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch which introduces more than one new commit,
        # which we expect the commit-extra-checker to accept.
        #
        # Note that the remote repository was deliberately set up to have
        # a branch named future-multiple-commits-accept-some-preexisting
        # which already includes two of the 3 commits this branch updates.
        # In other words, prior to the push, we have the following layout
        # (left to right is parent to child):
        #
        #     A <-- origin/multiple-commits-accept-some-preexisting
        #       \__ B <-- C <-- origin/future-multiple-commits-accept-some-preexisting
        #                   \__ D <-- multiple-commits-accept-some-preexisting
        #
        # The push will add commits B, C and D to the remote's
        # multiple-commits-accept-some-preexisting branch. The fact the branch
        # future-multiple-commits-accept-some-preexisting already has commits
        # B and C means that those commits shouldn't be checked. This is
        # consistent with the policy that we follow for all the other checks
        # on commits. One extreme example of why this is important is when
        # creating a new branch from an existing one. If the existing branch
        # had a very large number of commits (e.g. the GCC's master branch
        # has ~180,000 commits as of 2020-10-02), it would be as many unwanted
        # calls to the commit checkers!

        p = Run(
            'git push origin multiple-commits-accept-some-preexisting'.split())
        expected_out = """\
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-accept-some-preexisting 25f07c061174291b3126b1df487937ea3408f291
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Really fix `a' this time (I think?!?)", "author_email": "*****@*****.**", "subject": "Really fix `a' this time (I think?!?)", "object_type": "commit", "rev": "25f07c061174291b3126b1df487937ea3408f291", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-accept-some-preexisting"}
remote: ---[ end stdin ]---
remote: DEBUG: Sending email: [repo/multiple-commits-accept-some-preexisting] Modify `a' and add `b'...
remote: DEBUG: inter-email delay...
remote: DEBUG: Sending email: [repo/multiple-commits-accept-some-preexisting] Fix `a' and delete `b' (no longer needed, after all)...
remote: DEBUG: inter-email delay...
remote: DEBUG: Sending email: [repo/multiple-commits-accept-some-preexisting] Really fix `a' this time (I think?!?)...
To ../bare/repo.git
   1e1e706..25f07c0  multiple-commits-accept-some-preexisting -> multiple-commits-accept-some-preexisting
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch which introduces more than one new commit, with
        # the first one expected to be rejected by commit-extra-checker
        # (we should see the checker only be called once).

        p = Run('git push origin multiple-commits-reject-first'.split())
        expected_out = """\
remote: *** The following commit was rejected by your hooks.commit-extra-checker script (status: 1)
remote: *** commit: 8ce0d28d635cd7dd490f6d574baecf079fd363d3
remote: *** DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-first 8ce0d28d635cd7dd490f6d574baecf079fd363d3
remote: *** -----[ stdin ]-----
remote: *** {"ref_kind": "branch", "body": "Modify `a' and add `b' (bad-commit)", "author_email": "*****@*****.**", "subject": "Modify `a' and add `b' (bad-commit)", "object_type": "commit", "rev": "8ce0d28d635cd7dd490f6d574baecf079fd363d3", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-first"}
remote: *** ---[ end stdin ]---
remote: *** Error: Invalid bla bla bla. Rejecting Update.
remote: error: hook declined to update refs/heads/multiple-commits-reject-first
To ../bare/repo.git
 ! [remote rejected] multiple-commits-reject-first -> multiple-commits-reject-first (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch which introduces more than one new commit, with
        # the second one (explicitly chosen to not be first nor last)
        # expected to be rejected by commit-extra-checker (we should see
        # the checker  be called exactly twice).
        #
        # Note that the output in which the calls to the checker is
        # printed in the output is out of order. I believe this is Git
        # printing stderr contents ahead of stdout. Accept that
        # pre-existing behavior.

        p = Run('git push origin multiple-commits-reject-middle'.split())
        expected_out = """\
remote: *** The following commit was rejected by your hooks.commit-extra-checker script (status: 1)
remote: *** commit: 6822734adebb636e8d3f9e664215d56f3d319282
remote: *** DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-middle 6822734adebb636e8d3f9e664215d56f3d319282
remote: *** -----[ stdin ]-----
remote: *** {"ref_kind": "branch", "body": "Fix `a' and delete `b' (bad-commit)", "author_email": "*****@*****.**", "subject": "Fix `a' and delete `b' (bad-commit)", "object_type": "commit", "rev": "6822734adebb636e8d3f9e664215d56f3d319282", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-middle"}
remote: *** ---[ end stdin ]---
remote: *** Error: Invalid bla bla bla. Rejecting Update.
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-middle 26107593d14c75d8146f24d635a7f3b3a4282e37
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Modify `a' and add `b'", "author_email": "*****@*****.**", "subject": "Modify `a' and add `b'", "object_type": "commit", "rev": "26107593d14c75d8146f24d635a7f3b3a4282e37", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-middle"}
remote: ---[ end stdin ]---
remote: error: hook declined to update refs/heads/multiple-commits-reject-middle
To ../bare/repo.git
 ! [remote rejected] multiple-commits-reject-middle -> multiple-commits-reject-middle (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # multiple-commits-reject-last
        #   + Modify `a' and add `b'
        #   + Fix `a' and delete `b' (no longer needed, after all)
        #   + Really fix `a' this time (bad-commit)

        # Push a branch which introduces more than one new commit, with
        # the second one (explicitly chosen to not be first nor last)
        # expected to be rejected by commit-extra-checker (we should see
        # the checker  be called exactly twice).
        #
        # Note that the output in which the calls to the checker is
        # printed in the output is out of order. I believe this is Git
        # printing stderr contents ahead of stdout. Accept that
        # pre-existing behavior.

        p = Run('git push origin multiple-commits-reject-last'.split())
        expected_out = """\
remote: *** The following commit was rejected by your hooks.commit-extra-checker script (status: 1)
remote: *** commit: d2593aef8aaaef1a6a43336277afe5c02b2fe04e
remote: *** DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-last d2593aef8aaaef1a6a43336277afe5c02b2fe04e
remote: *** -----[ stdin ]-----
remote: *** {"ref_kind": "branch", "body": "Really fix `a' this time (bad-commit)", "author_email": "*****@*****.**", "subject": "Really fix `a' this time (bad-commit)", "object_type": "commit", "rev": "d2593aef8aaaef1a6a43336277afe5c02b2fe04e", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-last"}
remote: *** ---[ end stdin ]---
remote: *** Error: Invalid bla bla bla. Rejecting Update.
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-last 37b8b3265f6649a0609d3473f932c55cfbe1b186
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Modify `a' and add `b'", "author_email": "*****@*****.**", "subject": "Modify `a' and add `b'", "object_type": "commit", "rev": "37b8b3265f6649a0609d3473f932c55cfbe1b186", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-last"}
remote: ---[ end stdin ]---
remote: DEBUG: commit-extra-checker.py refs/heads/multiple-commits-reject-last 3df475a99cc07966432aaf471054ead01a7a8cbb
remote: -----[ stdin ]-----
remote: {"ref_kind": "branch", "body": "Fix `a' and delete `b' (no longer needed, after all)", "author_email": "*****@*****.**", "subject": "Fix `a' and delete `b' (no longer needed, after all)", "object_type": "commit", "rev": "3df475a99cc07966432aaf471054ead01a7a8cbb", "author_name": "Joel Brobecker", "ref_name": "refs/heads/multiple-commits-reject-last"}
remote: ---[ end stdin ]---
remote: error: hook declined to update refs/heads/multiple-commits-reject-last
To ../bare/repo.git
 ! [remote rejected] multiple-commits-reject-last -> multiple-commits-reject-last (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a new branch, and verify that our commit-extra-checker
        # gets called (and rejects the push because of a bad commit).

        p = Run(
            'git push origin new-branch-multiple-commits-reject-first'.split())
        expected_out = """\
remote: *** The following commit was rejected by your hooks.commit-extra-checker script (status: 1)
remote: *** commit: 8ce0d28d635cd7dd490f6d574baecf079fd363d3
remote: *** DEBUG: commit-extra-checker.py refs/heads/new-branch-multiple-commits-reject-first 8ce0d28d635cd7dd490f6d574baecf079fd363d3
remote: *** -----[ stdin ]-----
remote: *** {"ref_kind": "branch", "body": "Modify `a' and add `b' (bad-commit)", "author_email": "*****@*****.**", "subject": "Modify `a' and add `b' (bad-commit)", "object_type": "commit", "rev": "8ce0d28d635cd7dd490f6d574baecf079fd363d3", "author_name": "Joel Brobecker", "ref_name": "refs/heads/new-branch-multiple-commits-reject-first"}
remote: *** ---[ end stdin ]---
remote: *** Error: Invalid bla bla bla. Rejecting Update.
remote: error: hook declined to update refs/heads/new-branch-multiple-commits-reject-first
To ../bare/repo.git
 ! [remote rejected] new-branch-multiple-commits-reject-first -> new-branch-multiple-commits-reject-first (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push a branch deletion. Our commit-extra-checker shouldn't
        # get called, since there are no new commits.

        p = Run('git push origin :delete-me'.split())
        expected_out = """\
remote: DEBUG: Sending email: [repo] Deleted branch 'delete-me'...
To ../bare/repo.git
 - [deleted]         delete-me
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #13
0
    def test_create_branch_with_custom_name(self):
        """Create a new branch with a standard reference name.
        """
        cd('%s/repo' % TEST_DIR)

        # First, try pushing with a branch name which is recognized
        # by the repository's branch namespace.

        p = Run('git push origin master:refs/user/someone'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Created branch 'someone' in namespace 'refs/user'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/user/someone
remote: X-Git-Oldrev: 0000000000000000000000000000000000000000
remote: X-Git-Newrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote:
remote: The branch 'someone' was created in namespace 'refs/user' pointing to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 * [new branch]      master -> refs/user/someone
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Next, try pushing with a branch name which is not recognized
        # by the repository's branch namespace. E.g., try creating
        # a "release-y" branch directly in "refs/heads".

        p = Run('git push origin master:refs/not/recognized'.split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/not/recognized
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/master
remote: ***       refs/heads/branches/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/not/recognized
To ../bare/repo.git
 ! [remote rejected] master -> refs/not/recognized (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #14
0
    def test_delete_branch_with_standard_name(self):
        """Delete a new branch with a standard reference name.
        """
        cd('%s/repo' % TEST_DIR)

        # First, try deleting with a branch name which exists and
        # is recognized by the repository's branch namespace.

        p = Run('git push origin :branches/release-x'.split())
        expected_out = """\
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Subject: [repo] Deleted branch 'branches/release-x'
remote: X-Act-Checkin: repo
remote: X-Git-Author: Test Suite <*****@*****.**>
remote: X-Git-Refname: refs/heads/branches/release-x
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 0000000000000000000000000000000000000000
remote:
remote: The branch 'branches/release-x' was deleted.
remote: It previously pointed to:
remote:
remote:  d065089... New file: a.
To ../bare/repo.git
 - [deleted]         branches/release-x
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Next, try deleting a branch which does not exist.

        p = Run('git push origin :branches/release-y'.split())
        expected_out = """\
error: unable to delete 'branches/release-y': remote ref does not exist
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Try deleting a branch which exists, but is not recognized
        # as a valid reference name for a branch.

        p = Run('git push origin :my-topic'.split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/heads/my-topic
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/master
remote: ***       refs/heads/branches/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/heads/my-topic
To ../bare/repo.git
 ! [remote rejected] my-topic (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #15
0
    def test_update_branch_in_standard_namespace(self):
        """Create a new branch with a standard reference name.
        """
        cd('%s/repo' % TEST_DIR)

        # First, try pushing with a branch name which is recognized
        # by the repository's branch namespace.

        p = Run('git push origin master'.split())
        expected_out = """\
remote: *** cvs_check: `repo' < `a'
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo] Update a
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/heads/master
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 5f5c774e41a5731382823de67459efbaf69e1e71
remote:
remote: commit 5f5c774e41a5731382823de67459efbaf69e1e71
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Apr 12 17:50:32 2020 -0700
remote:
remote:     Update a
remote:
remote: Diff:
remote: ---
remote:  a | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/a b/a
remote: index 01d0f12..fb08cf4 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1,3 +1,4 @@
remote:  Some file.
remote:  Second line.
remote:  Third line.
remote: +The end.
To ../bare/repo.git
   d065089..5f5c774  master -> master
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Next, try pushing with a branch name which is not recognized
        # by the repository's branch namespace. E.g., try updating
        # the branch called "my-topic", which exists in the remote
        # repository, but is not recognized as a branch reference
        # (could be a legacy branch).

        p = Run('git push origin my-topic'.split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/heads/my-topic
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/master
remote: ***       refs/heads/branches/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/heads/my-topic
To ../bare/repo.git
 ! [remote rejected] my-topic -> my-topic (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #16
0
    def test_update_branch_in_custom_namespace(self):
        """Create a new branch with a custom reference name.
        """
        cd('%s/repo' % TEST_DIR)

        # First, try pushing with a branch name which is recognized
        # by the repository's branch namespace.

        p = Run('git push origin my-topic:refs/user/myself/my-feature'.split())
        expected_out = """\
remote: *** cvs_check: `repo' < `a'
remote: DEBUG: Content-Type: text/plain; charset="us-ascii"
remote: MIME-Version: 1.0
remote: Content-Transfer-Encoding: 7bit
remote: From: Test Suite <*****@*****.**>
remote: To: [email protected]
remote: Bcc: [email protected]
remote: Subject: [repo(refs/user/myself/my-feature)] update a to add terminator line
remote: X-Act-Checkin: repo
remote: X-Git-Author: Joel Brobecker <*****@*****.**>
remote: X-Git-Refname: refs/user/myself/my-feature
remote: X-Git-Oldrev: d065089ff184d97934c010ccd0e7e8ed94cb7165
remote: X-Git-Newrev: 2a112bb1c30346f6287bb3d5c157a93235ea861f
remote:
remote: commit 2a112bb1c30346f6287bb3d5c157a93235ea861f
remote: Author: Joel Brobecker <*****@*****.**>
remote: Date:   Sun Mar 1 20:15:13 2020 +0400
remote:
remote:     update a to add terminator line
remote:
remote: Diff:
remote: ---
remote:  a | 1 +
remote:  1 file changed, 1 insertion(+)
remote:
remote: diff --git a/a b/a
remote: index 01d0f12..698778b 100644
remote: --- a/a
remote: +++ b/a
remote: @@ -1,3 +1,4 @@
remote:  Some file.
remote:  Second line.
remote:  Third line.
remote: +Terminator.
To ../bare/repo.git
   d065089..2a112bb  my-topic -> refs/user/myself/my-feature
"""

        self.assertEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Next, try pushing with a branch name which is not recognized
        # by the repository's branch namespace.

        p = Run('git push origin my-topic:refs/others/exists-but-unrecognized'.
                split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/others/exists-but-unrecognized
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/master
remote: ***       refs/heads/branches/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/others/exists-but-unrecognized
To ../bare/repo.git
 ! [remote rejected] my-topic -> refs/others/exists-but-unrecognized (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)
Exemple #17
0
    def test_update_branch_custom_name_not_recognized(self):
        """Push a branch updates using invalid custom reference names."""
        cd('%s/repo' % TEST_DIR)

        # Push to a reference which does exist in the remote repository,
        # but does not follow any of the repository's naming schemes.
        p = Run('git push origin my-topic:refs/others/exists-but-unrecognized'.
                split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/others/exists-but-unrecognized
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/.*
remote: ***       refs/meta/.*
remote: ***       refs/drafts/.*
remote: ***       refs/for/.*
remote: ***       refs/publish/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/others/exists-but-unrecognized
To ../bare/repo.git
 ! [remote rejected] my-topic -> refs/others/exists-but-unrecognized (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)

        # Push to a reference which does not exist in the remote
        # repository, and whose name does not follow any of the
        # repository's naming schemes.
        p = Run(
            'git push origin my-topic:refs/does-not-exist/my-feature'.split())
        expected_out = """\
remote: *** Unable to determine the type of reference for: refs/does-not-exist/my-feature
remote: ***
remote: *** This repository currently recognizes the following types
remote: *** of references:
remote: ***
remote: ***  * Branches:
remote: ***       refs/heads/.*
remote: ***       refs/meta/.*
remote: ***       refs/drafts/.*
remote: ***       refs/for/.*
remote: ***       refs/publish/.*
remote: ***       refs/vendor/.*
remote: ***       refs/user/.*
remote: ***
remote: ***  * Git Notes:
remote: ***       refs/notes/.*
remote: ***
remote: ***  * Tags:
remote: ***       refs/tags/.*
remote: error: hook declined to update refs/does-not-exist/my-feature
To ../bare/repo.git
 ! [remote rejected] my-topic -> refs/does-not-exist/my-feature (hook declined)
error: failed to push some refs to '../bare/repo.git'
"""

        self.assertNotEqual(p.status, 0, p.image)
        self.assertRunOutputEqual(p, expected_out)