test_pagure_flask_ui_pr_no_sources.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. __requires__ = ['SQLAlchemy >= 0.8']
  8. import pkg_resources
  9. import json
  10. import unittest
  11. import shutil
  12. import sys
  13. import tempfile
  14. import time
  15. import os
  16. import pygit2
  17. from mock import patch, MagicMock
  18. sys.path.insert(0, os.path.join(os.path.dirname(
  19. os.path.abspath(__file__)), '..'))
  20. import pagure
  21. import pagure.lib
  22. import tests
  23. from pagure.lib.repo import PagureRepo
  24. class PagureFlaskPrNoSourcestests(tests.Modeltests):
  25. """ Tests PR in pagure when the source is gone """
  26. maxDiff = None
  27. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  28. @patch('pagure.lib.notify.fedmsg_publish', MagicMock(return_value=True))
  29. def setUp(self):
  30. """ Set up the environnment, ran before every tests. """
  31. super(PagureFlaskPrNoSourcestests, self).setUp()
  32. tests.create_projects(self.session)
  33. tests.create_projects_git(
  34. os.path.join(self.path, 'repos'), bare=True)
  35. # Create foo's fork of pingou's test project
  36. item = pagure.lib.model.Project(
  37. user_id=2, # foo
  38. name='test',
  39. description='test project #1',
  40. hook_token='aaabbb',
  41. is_fork=True,
  42. parent_id=1,
  43. )
  44. self.session.add(item)
  45. self.session.commit()
  46. # Create the fork's git repo
  47. repo_path = os.path.join(self.path, 'repos', item.path)
  48. pygit2.init_repository(repo_path, bare=True)
  49. project = pagure.lib.get_authorized_project(self.session, 'test')
  50. fork = pagure.lib.get_authorized_project(
  51. self.session, 'test', user='foo')
  52. self.set_up_git_repo(repo=project, fork=fork)
  53. # Ensure things got setup straight
  54. project = pagure.lib.get_authorized_project(self.session, 'test')
  55. self.assertEqual(len(project.requests), 1)
  56. # wait for the worker to process the task
  57. path = os.path.join(
  58. self.path, 'repos', 'test.git',
  59. 'refs', 'pull', '1', 'head')
  60. cnt = 0
  61. while not os.path.exists(path):
  62. time.sleep(0.1)
  63. cnt += 1
  64. if cnt == 100:
  65. # We're about 10 seconds in, let's bail
  66. raise Exception('Sorry, worker took too long')
  67. def set_up_git_repo(self, repo, fork, branch_from='feature'):
  68. """ Set up the git repo and create the corresponding PullRequest
  69. object.
  70. """
  71. # Clone the main repo
  72. gitrepo = os.path.join(self.path, 'repos', repo.path)
  73. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  74. repopath = os.path.join(newpath, 'test')
  75. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  76. # Create a file in that git repo
  77. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  78. stream.write('foo\n bar')
  79. clone_repo.index.add('sources')
  80. clone_repo.index.write()
  81. # Commits the files added
  82. tree = clone_repo.index.write_tree()
  83. author = pygit2.Signature(
  84. 'Alice Author', 'alice@authors.tld')
  85. committer = pygit2.Signature(
  86. 'Cecil Committer', 'cecil@committers.tld')
  87. clone_repo.create_commit(
  88. 'refs/heads/master', # the name of the reference to update
  89. author,
  90. committer,
  91. 'Add sources file for testing',
  92. # binary string representing the tree object ID
  93. tree,
  94. # list of binary strings representing parents of the new commit
  95. []
  96. )
  97. refname = 'refs/heads/master:refs/heads/master'
  98. ori_remote = clone_repo.remotes[0]
  99. PagureRepo.push(ori_remote, refname)
  100. first_commit = clone_repo.revparse_single('HEAD')
  101. # Set the second repo
  102. repopath = os.path.join(self.path, 'repos', fork.path)
  103. new_gitrepo = os.path.join(newpath, 'fork_test')
  104. clone_repo = pygit2.clone_repository(repopath, new_gitrepo)
  105. # Add the main project as remote repo
  106. upstream_path = os.path.join(self.path, 'repos', repo.path)
  107. remote = clone_repo.create_remote('upstream', upstream_path)
  108. remote.fetch()
  109. # Edit the sources file again
  110. with open(os.path.join(new_gitrepo, 'sources'), 'w') as stream:
  111. stream.write('foo\n bar\nbaz\n boose')
  112. clone_repo.index.add('sources')
  113. clone_repo.index.write()
  114. # Commits the files added
  115. tree = clone_repo.index.write_tree()
  116. author = pygit2.Signature(
  117. 'Alice Author', 'alice@authors.tld')
  118. committer = pygit2.Signature(
  119. 'Cecil Committer', 'cecil@committers.tld')
  120. clone_repo.create_commit(
  121. 'refs/heads/%s' % branch_from,
  122. author,
  123. committer,
  124. 'A commit on branch %s' % branch_from,
  125. tree,
  126. [first_commit.oid.hex]
  127. )
  128. refname = 'refs/heads/%s' % (branch_from)
  129. ori_remote = clone_repo.remotes[0]
  130. PagureRepo.push(ori_remote, refname)
  131. # Create a PR for these changes
  132. project = pagure.lib.get_authorized_project(self.session, 'test')
  133. req = pagure.lib.new_pull_request(
  134. session=self.session,
  135. repo_from=fork,
  136. branch_from=branch_from,
  137. repo_to=project,
  138. branch_to='master',
  139. title='PR from the %s branch' % branch_from,
  140. user='pingou',
  141. requestfolder=None,
  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. output2 = self.app.get('/test/pull-request/1.patch')
  197. self.assertEqual(output2.status_code, 200)
  198. self.assertIn(
  199. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  200. output2.data)
  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. output2 = self.app.get('/test/pull-request/1.patch')
  256. self.assertEqual(output2.status_code, 200)
  257. self.assertIn(
  258. '--- a/sources\n+++ b/sources\n@@ -1,2 +1,4 @@',
  259. output2.data)
  260. if __name__ == '__main__':
  261. unittest.main(verbosity=2)