test_pagure_flask_ui_pr_no_sources.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals, absolute_import
  8. import json
  9. import unittest
  10. import shutil
  11. import sys
  12. import tempfile
  13. import time
  14. import os
  15. import pygit2
  16. from mock import patch, MagicMock
  17. sys.path.insert(0, os.path.join(os.path.dirname(
  18. os.path.abspath(__file__)), '..'))
  19. import pagure.lib.query
  20. import tests
  21. from pagure.lib.repo import PagureRepo
  22. class PagureFlaskPrNoSourcestests(tests.Modeltests):
  23. """ Tests PR in pagure when the source is gone """
  24. maxDiff = None
  25. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  26. @patch('pagure.lib.notify.fedmsg_publish', MagicMock(return_value=True))
  27. def setUp(self):
  28. """ Set up the environnment, ran before every tests. """
  29. super(PagureFlaskPrNoSourcestests, self).setUp()
  30. tests.create_projects(self.session)
  31. tests.create_projects_git(
  32. os.path.join(self.path, 'repos'), bare=True)
  33. # Create foo's fork of pingou's test project
  34. item = pagure.lib.model.Project(
  35. user_id=2, # foo
  36. name='test',
  37. description='test project #1',
  38. hook_token='aaabbb',
  39. is_fork=True,
  40. parent_id=1,
  41. )
  42. self.session.add(item)
  43. self.session.commit()
  44. # Create the fork's git repo
  45. repo_path = os.path.join(self.path, 'repos', item.path)
  46. pygit2.init_repository(repo_path, bare=True)
  47. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  48. fork = pagure.lib.query.get_authorized_project(
  49. self.session, 'test', user='foo')
  50. self.set_up_git_repo(repo=project, fork=fork)
  51. # Ensure things got setup straight
  52. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  53. self.assertEqual(len(project.requests), 1)
  54. # wait for the worker to process the task
  55. path = os.path.join(
  56. self.path, 'repos', 'test.git',
  57. 'refs', 'pull', '1', 'head')
  58. self.assertTrue(os.path.exists(path))
  59. def set_up_git_repo(self, repo, fork, branch_from='feature'):
  60. """ Set up the git repo and create the corresponding PullRequest
  61. object.
  62. """
  63. # Clone the main repo
  64. gitrepo = os.path.join(self.path, 'repos', repo.path)
  65. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  66. repopath = os.path.join(newpath, 'test')
  67. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  68. # Create a file in that git repo
  69. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  70. stream.write('foo\n bar')
  71. clone_repo.index.add('sources')
  72. clone_repo.index.write()
  73. # Commits the files added
  74. tree = clone_repo.index.write_tree()
  75. author = pygit2.Signature(
  76. 'Alice Author', 'alice@authors.tld')
  77. committer = pygit2.Signature(
  78. 'Cecil Committer', 'cecil@committers.tld')
  79. clone_repo.create_commit(
  80. 'refs/heads/master', # the name of the reference to update
  81. author,
  82. committer,
  83. 'Add sources file for testing',
  84. # binary string representing the tree object ID
  85. tree,
  86. # list of binary strings representing parents of the new commit
  87. []
  88. )
  89. refname = 'refs/heads/master:refs/heads/master'
  90. ori_remote = clone_repo.remotes[0]
  91. PagureRepo.push(ori_remote, refname)
  92. first_commit = clone_repo.revparse_single('HEAD')
  93. # Set the second repo
  94. repopath = os.path.join(self.path, 'repos', fork.path)
  95. new_gitrepo = os.path.join(newpath, 'fork_test')
  96. clone_repo = pygit2.clone_repository(repopath, new_gitrepo)
  97. # Add the main project as remote repo
  98. upstream_path = os.path.join(self.path, 'repos', repo.path)
  99. remote = clone_repo.create_remote('upstream', upstream_path)
  100. remote.fetch()
  101. # Edit the sources file again
  102. with open(os.path.join(new_gitrepo, 'sources'), 'w') as stream:
  103. stream.write('foo\n bar\nbaz\n boose')
  104. clone_repo.index.add('sources')
  105. clone_repo.index.write()
  106. # Commits the files added
  107. tree = clone_repo.index.write_tree()
  108. author = pygit2.Signature(
  109. 'Alice Author', 'alice@authors.tld')
  110. committer = pygit2.Signature(
  111. 'Cecil Committer', 'cecil@committers.tld')
  112. clone_repo.create_commit(
  113. 'refs/heads/%s' % branch_from,
  114. author,
  115. committer,
  116. 'A commit on branch %s' % branch_from,
  117. tree,
  118. [first_commit.oid.hex]
  119. )
  120. refname = 'refs/heads/%s' % (branch_from)
  121. ori_remote = clone_repo.remotes[0]
  122. PagureRepo.push(ori_remote, refname)
  123. # Create a PR for these changes
  124. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  125. req = pagure.lib.query.new_pull_request(
  126. session=self.session,
  127. repo_from=fork,
  128. branch_from=branch_from,
  129. repo_to=project,
  130. branch_to='master',
  131. title='PR from the %s branch' % branch_from,
  132. user='pingou',
  133. )
  134. self.session.commit()
  135. self.assertEqual(req.id, 1)
  136. self.assertEqual(req.title, 'PR from the %s branch' % branch_from)
  137. shutil.rmtree(newpath)
  138. def test_request_pull_reference(self):
  139. """ Test if there is a reference created for a new PR. """
  140. project = pagure.lib.query.get_authorized_project(self.session, 'test')
  141. self.assertEqual(len(project.requests), 1)
  142. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  143. repo = pygit2.Repository(gitrepo)
  144. self.assertEqual(
  145. list(repo.listall_references()),
  146. ['refs/heads/master', 'refs/pull/1/head']
  147. )
  148. def test_request_pull_fork_reference(self):
  149. """ Test if there the references created on the fork. """
  150. project = pagure.lib.query.get_authorized_project(
  151. self.session, 'test', user='foo')
  152. self.assertEqual(len(project.requests), 0)
  153. gitrepo = os.path.join(self.path, 'repos', project.path)
  154. repo = pygit2.Repository(gitrepo)
  155. self.assertEqual(
  156. list(repo.listall_references()),
  157. ['refs/heads/feature']
  158. )
  159. def test_accessing_pr_fork_deleted(self):
  160. """ Test accessing the PR if the fork has been deleted. """
  161. # Delete fork on disk
  162. project = pagure.lib.query.get_authorized_project(
  163. self.session, 'test', user='foo')
  164. repo_path = os.path.join(self.path, 'repos', project.path)
  165. self.assertTrue(os.path.exists(repo_path))
  166. shutil.rmtree(repo_path)
  167. self.assertFalse(os.path.exists(repo_path))
  168. # Delete fork in the DB
  169. self.session.delete(project)
  170. self.session.commit()
  171. # View the pull-request
  172. output2 = self.app.get('/test/pull-request/1')
  173. self.assertEqual(output2.status_code, 200)
  174. def test_accessing_pr_patch_fork_deleted(self):
  175. """ Test accessing the PR's patch if the fork has been deleted. """
  176. # Delete fork on disk
  177. project = pagure.lib.query.get_authorized_project(
  178. self.session, 'test', user='foo')
  179. repo_path = os.path.join(self.path, 'repos', project.path)
  180. self.assertTrue(os.path.exists(repo_path))
  181. shutil.rmtree(repo_path)
  182. self.assertFalse(os.path.exists(repo_path))
  183. # Delete fork in the DB
  184. self.session.delete(project)
  185. self.session.commit()
  186. # View the pull-request
  187. output = self.app.get('/test/pull-request/1.patch')
  188. self.assertEqual(output.status_code, 200)
  189. self.assertIn(
  190. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  191. output.get_data(as_text=True))
  192. def test_accessing_pr_branch_deleted(self):
  193. """ Test accessing the PR if branch it originates from has been
  194. deleted. """
  195. project = pagure.lib.query.get_authorized_project(
  196. self.session, 'test', user='foo')
  197. # Check the branches before
  198. gitrepo = os.path.join(self.path, 'repos', project.path)
  199. repo = pygit2.Repository(gitrepo)
  200. self.assertEqual(
  201. list(repo.listall_references()),
  202. ['refs/heads/feature']
  203. )
  204. # Delete branch of the fork
  205. user = tests.FakeUser(username='foo')
  206. with tests.user_set(self.app.application, user):
  207. output = self.app.post(
  208. '/fork/foo/test/b/feature/delete', follow_redirects=True)
  209. self.assertEqual(output.status_code, 200)
  210. # Check the branches after
  211. gitrepo = os.path.join(self.path, 'repos', project.path)
  212. repo = pygit2.Repository(gitrepo)
  213. self.assertEqual(
  214. list(repo.listall_references()),
  215. []
  216. )
  217. # View the pull-request
  218. output2 = self.app.get('/test/pull-request/1')
  219. self.assertEqual(output2.status_code, 200)
  220. def test_accessing_pr_patch_branch_deleted(self):
  221. """ Test accessing the PR's patch if branch it originates from has
  222. been deleted. """
  223. project = pagure.lib.query.get_authorized_project(
  224. self.session, 'test', user='foo')
  225. # Check the branches before
  226. gitrepo = os.path.join(self.path, 'repos', project.path)
  227. repo = pygit2.Repository(gitrepo)
  228. self.assertEqual(
  229. list(repo.listall_references()),
  230. ['refs/heads/feature']
  231. )
  232. # Delete branch of the fork
  233. user = tests.FakeUser(username='foo')
  234. with tests.user_set(self.app.application, user):
  235. output = self.app.post(
  236. '/fork/foo/test/b/feature/delete', follow_redirects=True)
  237. self.assertEqual(output.status_code, 200)
  238. # Check the branches after
  239. gitrepo = os.path.join(self.path, 'repos', project.path)
  240. repo = pygit2.Repository(gitrepo)
  241. self.assertEqual(
  242. list(repo.listall_references()),
  243. []
  244. )
  245. # View the pull-request
  246. output = self.app.get('/test/pull-request/1.patch')
  247. self.assertEqual(output.status_code, 200)
  248. self.assertIn(
  249. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  250. output.get_data(as_text=True))
  251. if __name__ == '__main__':
  252. unittest.main(verbosity=2)