test_pagure_flask_ui_pr_no_sources.py 11 KB

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