test_pagure_flask_internal.py 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2017 - 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 datetime
  11. import json
  12. import unittest
  13. import shutil
  14. import sys
  15. import time
  16. import os
  17. import pygit2
  18. from mock import patch
  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 PagureFlaskInternaltests(tests.Modeltests):
  26. """ Tests for flask Internal controller of pagure """
  27. def setUp(self):
  28. """ Set up the environnment, ran before every tests. """
  29. super(PagureFlaskInternaltests, self).setUp()
  30. pagure.config.config['IP_ALLOWED_INTERNAL'] = list(set(
  31. pagure.config.config['IP_ALLOWED_INTERNAL'] + [None]))
  32. pagure.config.config['GIT_FOLDER'] = os.path.join(
  33. self.path, 'repos')
  34. pagure.config.config['REQUESTS_FOLDER'] = None
  35. pagure.config.config['TICKETS_FOLDER'] = None
  36. pagure.config.config['DOCS_FOLDER'] = None
  37. @patch('pagure.lib.notify.send_email')
  38. def test_pull_request_add_comment(self, send_email):
  39. """ Test the pull_request_add_comment function. """
  40. send_email.return_value = True
  41. tests.create_projects(self.session)
  42. repo = pagure.lib.get_authorized_project(self.session, 'test')
  43. req = pagure.lib.new_pull_request(
  44. session=self.session,
  45. repo_from=repo,
  46. branch_from='feature',
  47. repo_to=repo,
  48. branch_to='master',
  49. title='PR from the feature branch',
  50. user='pingou',
  51. requestfolder=None,
  52. )
  53. self.session.commit()
  54. self.assertEqual(req.id, 1)
  55. self.assertEqual(req.title, 'PR from the feature branch')
  56. request = repo.requests[0]
  57. self.assertEqual(len(request.comments), 0)
  58. self.assertEqual(len(request.discussion), 0)
  59. data = {
  60. 'objid': 'foo',
  61. }
  62. # Wrong http request
  63. output = self.app.post('/pv/pull-request/comment/', data=data)
  64. self.assertEqual(output.status_code, 405)
  65. # Invalid request
  66. output = self.app.put('/pv/pull-request/comment/', data=data)
  67. self.assertEqual(output.status_code, 400)
  68. data = {
  69. 'objid': 'foo',
  70. 'useremail': 'foo@pingou.com',
  71. }
  72. # Invalid objid
  73. output = self.app.put('/pv/pull-request/comment/', data=data)
  74. self.assertEqual(output.status_code, 404)
  75. data = {
  76. 'objid': request.uid,
  77. 'useremail': 'foo@pingou.com',
  78. }
  79. # Valid objid, in-complete data for a comment
  80. output = self.app.put('/pv/pull-request/comment/', data=data)
  81. self.assertEqual(output.status_code, 400)
  82. data = {
  83. 'objid': request.uid,
  84. 'useremail': 'foo@pingou.com',
  85. 'comment': 'Looks good to me!',
  86. }
  87. # Add comment
  88. output = self.app.put('/pv/pull-request/comment/', data=data)
  89. self.assertEqual(output.status_code, 200)
  90. js_data = json.loads(output.get_data(as_text=True))
  91. self.assertDictEqual(js_data, {'message': 'Comment added'})
  92. self.session.commit()
  93. repo = pagure.lib.get_authorized_project(self.session, 'test')
  94. request = repo.requests[0]
  95. self.assertEqual(len(request.comments), 1)
  96. self.assertEqual(len(request.discussion), 1)
  97. # Check the @localonly
  98. before = pagure.config.config['IP_ALLOWED_INTERNAL'][:]
  99. pagure.config.config['IP_ALLOWED_INTERNAL'] = []
  100. output = self.app.put('/pv/pull-request/comment/', data=data)
  101. self.assertEqual(output.status_code, 403)
  102. pagure.config.config['IP_ALLOWED_INTERNAL'] = before[:]
  103. @patch('pagure.lib.notify.send_email')
  104. def test_ticket_add_comment(self, send_email):
  105. """ Test the ticket_add_comment function. """
  106. send_email.return_value = True
  107. tests.create_projects(self.session)
  108. # Create issues to play with
  109. repo = pagure.lib.get_authorized_project(self.session, 'test')
  110. msg = pagure.lib.new_issue(
  111. session=self.session,
  112. repo=repo,
  113. title='Test issue',
  114. content='We should work on this',
  115. user='pingou',
  116. ticketfolder=None
  117. )
  118. self.session.commit()
  119. self.assertEqual(msg.title, 'Test issue')
  120. issue = repo.issues[0]
  121. self.assertEqual(len(issue.comments), 0)
  122. data = {
  123. 'objid': 'foo',
  124. }
  125. # Wrong http request
  126. output = self.app.post('/pv/ticket/comment/', data=data)
  127. self.assertEqual(output.status_code, 405)
  128. # Invalid request
  129. output = self.app.put('/pv/ticket/comment/', data=data)
  130. self.assertEqual(output.status_code, 400)
  131. data = {
  132. 'objid': 'foo',
  133. 'useremail': 'foo@pingou.com',
  134. }
  135. # Invalid objid
  136. output = self.app.put('/pv/ticket/comment/', data=data)
  137. self.assertEqual(output.status_code, 404)
  138. data = {
  139. 'objid': issue.uid,
  140. 'useremail': 'foo@pingou.com',
  141. }
  142. # Valid objid, in-complete data for a comment
  143. output = self.app.put('/pv/ticket/comment/', data=data)
  144. self.assertEqual(output.status_code, 400)
  145. data = {
  146. 'objid': issue.uid,
  147. 'useremail': 'foo@pingou.com',
  148. 'comment': 'Looks good to me!',
  149. }
  150. # Add comment
  151. output = self.app.put('/pv/ticket/comment/', data=data)
  152. self.assertEqual(output.status_code, 200)
  153. js_data = json.loads(output.get_data(as_text=True))
  154. self.assertDictEqual(js_data, {'message': 'Comment added'})
  155. self.session.commit()
  156. repo = pagure.lib.get_authorized_project(self.session, 'test')
  157. issue = repo.issues[0]
  158. self.assertEqual(len(issue.comments), 1)
  159. # Check the @localonly
  160. pagure.config.config['IP_ALLOWED_INTERNAL'].remove(None)
  161. before = pagure.config.config['IP_ALLOWED_INTERNAL'][:]
  162. pagure.config.config['IP_ALLOWED_INTERNAL'] = []
  163. output = self.app.put('/pv/ticket/comment/', data=data)
  164. self.assertEqual(output.status_code, 403)
  165. pagure.config.config['IP_ALLOWED_INTERNAL'] = before[:]
  166. @patch('pagure.lib.notify.send_email')
  167. def test_private_ticket_add_comment(self, send_email):
  168. """ Test the ticket_add_comment function on a private ticket. """
  169. send_email.return_value = True
  170. tests.create_projects(self.session)
  171. # Create issues to play with
  172. repo = pagure.lib.get_authorized_project(self.session, 'test')
  173. msg = pagure.lib.new_issue(
  174. session=self.session,
  175. repo=repo,
  176. title='Test issue',
  177. content='We should work on this, really',
  178. user='pingou',
  179. private=True,
  180. ticketfolder=None
  181. )
  182. self.session.commit()
  183. self.assertEqual(msg.title, 'Test issue')
  184. issue = repo.issues[0]
  185. self.assertEqual(len(issue.comments), 0)
  186. data = {
  187. 'objid': 'foo',
  188. }
  189. # Wrong http request
  190. output = self.app.post('/pv/ticket/comment/', data=data)
  191. self.assertEqual(output.status_code, 405)
  192. # Invalid request
  193. output = self.app.put('/pv/ticket/comment/', data=data)
  194. self.assertEqual(output.status_code, 400)
  195. data = {
  196. 'objid': 'foo',
  197. 'useremail': 'foo@pingou.com',
  198. }
  199. # Invalid objid
  200. output = self.app.put('/pv/ticket/comment/', data=data)
  201. self.assertEqual(output.status_code, 404)
  202. data = {
  203. 'objid': issue.uid,
  204. 'useremail': 'foo@bar.com',
  205. }
  206. # Valid objid, un-allowed user for this (private) ticket
  207. output = self.app.put('/pv/ticket/comment/', data=data)
  208. self.assertEqual(output.status_code, 403)
  209. data = {
  210. 'objid': issue.uid,
  211. 'useremail': 'foo@pingou.com',
  212. }
  213. # Valid objid, un-allowed user for this (private) ticket
  214. output = self.app.put('/pv/ticket/comment/', data=data)
  215. self.assertEqual(output.status_code, 400)
  216. data = {
  217. 'objid': issue.uid,
  218. 'useremail': 'foo@pingou.com',
  219. 'comment': 'Looks good to me!',
  220. }
  221. # Add comment
  222. output = self.app.put('/pv/ticket/comment/', data=data)
  223. self.assertEqual(output.status_code, 200)
  224. js_data = json.loads(output.get_data(as_text=True))
  225. self.assertDictEqual(js_data, {'message': 'Comment added'})
  226. self.session.commit()
  227. repo = pagure.lib.get_authorized_project(self.session, 'test')
  228. issue = repo.issues[0]
  229. self.assertEqual(len(issue.comments), 1)
  230. # Check the @localonly
  231. before = pagure.config.config['IP_ALLOWED_INTERNAL'][:]
  232. pagure.config.config['IP_ALLOWED_INTERNAL'] = []
  233. output = self.app.put('/pv/ticket/comment/', data=data)
  234. self.assertEqual(output.status_code, 403)
  235. pagure.config.config['IP_ALLOWED_INTERNAL'] = before[:]
  236. @patch('pagure.lib.notify.send_email')
  237. def test_private_ticket_add_comment_acl(self, send_email):
  238. """ Test the ticket_add_comment function on a private ticket. """
  239. send_email.return_value = True
  240. tests.create_projects(self.session)
  241. # Create issues to play with
  242. repo = pagure.lib.get_authorized_project(self.session, 'test')
  243. msg = pagure.lib.new_issue(
  244. session=self.session,
  245. repo=repo,
  246. title='Test issue',
  247. content='We should work on this, really',
  248. user='pingou',
  249. private=True,
  250. ticketfolder=None
  251. )
  252. self.session.commit()
  253. self.assertEqual(msg.title, 'Test issue')
  254. repo = pagure.lib.get_authorized_project(self.session, 'test')
  255. issue = repo.issues[0]
  256. self.assertEqual(len(issue.comments), 0)
  257. # Currently, he is just an average user,
  258. # He doesn't have any access in this repo
  259. data = {
  260. 'objid': issue.uid,
  261. 'useremail': 'foo@bar.com',
  262. 'comment': 'Looks good to me!',
  263. }
  264. # Valid objid, un-allowed user for this (private) ticket
  265. output = self.app.put('/pv/ticket/comment/', data=data)
  266. self.assertEqual(output.status_code, 403)
  267. repo = pagure.lib.get_authorized_project(self.session, 'test')
  268. # Let's promote him to be a ticketer
  269. # He shoudn't be able to comment even then though
  270. msg = pagure.lib.add_user_to_project(
  271. self.session,
  272. project=repo,
  273. new_user='foo',
  274. user='pingou',
  275. access='ticket'
  276. )
  277. self.session.commit()
  278. self.assertEqual(msg, 'User added')
  279. repo = pagure.lib.get_authorized_project(self.session, 'test')
  280. self.assertEqual(
  281. sorted([u.username for u in repo.users]), ['foo'])
  282. self.assertEqual(
  283. sorted([u.username for u in repo.committers]), [])
  284. self.assertEqual(
  285. sorted([u.username for u in repo.admins]), [])
  286. output = self.app.put('/pv/ticket/comment/', data=data)
  287. self.assertEqual(output.status_code, 403)
  288. repo = pagure.lib.get_authorized_project(self.session, 'test')
  289. # Let's promote him to be a committer
  290. # He should be able to comment
  291. msg = pagure.lib.add_user_to_project(
  292. self.session,
  293. project=repo,
  294. new_user='foo',
  295. user='pingou',
  296. access='commit'
  297. )
  298. self.session.commit()
  299. self.assertEqual(msg, 'User access updated')
  300. repo = pagure.lib.get_authorized_project(self.session, 'test')
  301. self.assertEqual(
  302. sorted([u.username for u in repo.users]), ['foo'])
  303. self.assertEqual(
  304. sorted([u.username for u in repo.committers]), ['foo'])
  305. self.assertEqual(
  306. sorted([u.username for u in repo.admins]), [])
  307. # Add comment
  308. output = self.app.put('/pv/ticket/comment/', data=data)
  309. self.assertEqual(output.status_code, 200)
  310. js_data = json.loads(output.get_data(as_text=True))
  311. self.assertDictEqual(js_data, {'message': 'Comment added'})
  312. repo = pagure.lib.get_authorized_project(self.session, 'test')
  313. issue = repo.issues[0]
  314. self.assertEqual(len(issue.comments), 1)
  315. # Let's promote him to be a admin
  316. # He should be able to comment
  317. msg = pagure.lib.add_user_to_project(
  318. self.session,
  319. project=repo,
  320. new_user='foo',
  321. user='pingou',
  322. access='admin'
  323. )
  324. self.session.commit()
  325. self.assertEqual(msg, 'User access updated')
  326. repo = pagure.lib.get_authorized_project(self.session, 'test')
  327. self.assertEqual(
  328. sorted([u.username for u in repo.users]), ['foo'])
  329. self.assertEqual(
  330. sorted([u.username for u in repo.committers]), ['foo'])
  331. self.assertEqual(
  332. sorted([u.username for u in repo.admins]), ['foo'])
  333. # Add comment
  334. output = self.app.put('/pv/ticket/comment/', data=data)
  335. self.assertEqual(output.status_code, 200)
  336. js_data = json.loads(output.get_data(as_text=True))
  337. self.assertDictEqual(js_data, {'message': 'Comment added'})
  338. repo = pagure.lib.get_authorized_project(self.session, 'test')
  339. issue = repo.issues[0]
  340. self.assertEqual(len(issue.comments), 2)
  341. # Check the @localonly
  342. before = pagure.config.config['IP_ALLOWED_INTERNAL'][:]
  343. pagure.config.config['IP_ALLOWED_INTERNAL'] = []
  344. output = self.app.put('/pv/ticket/comment/', data=data)
  345. self.assertEqual(output.status_code, 403)
  346. pagure.config.config['IP_ALLOWED_INTERNAL'] = before[:]
  347. @patch('pagure.lib.notify.send_email')
  348. def test_mergeable_request_pull_FF(self, send_email):
  349. """ Test the mergeable_request_pull endpoint with a fast-forward
  350. merge.
  351. """
  352. send_email.return_value = True
  353. # Create a git repo to play with
  354. origgitrepo = os.path.join(self.path, 'repos', 'test.git')
  355. self.assertFalse(os.path.exists(origgitrepo))
  356. os.makedirs(origgitrepo)
  357. orig_repo = pygit2.init_repository(origgitrepo, bare=True)
  358. os.makedirs(os.path.join(self.path, 'repos_tmp'))
  359. gitrepo = os.path.join(self.path, 'repos_tmp', 'test.git')
  360. repo = pygit2.clone_repository(origgitrepo, gitrepo)
  361. # Create a file in that git repo
  362. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  363. stream.write('foo\n bar')
  364. repo.index.add('sources')
  365. repo.index.write()
  366. # Commits the files added
  367. tree = repo.index.write_tree()
  368. author = pygit2.Signature(
  369. 'Alice Author', 'alice@authors.tld')
  370. committer = pygit2.Signature(
  371. 'Cecil Committer', 'cecil@committers.tld')
  372. repo.create_commit(
  373. 'refs/heads/master', # the name of the reference to update
  374. author,
  375. committer,
  376. 'Add sources file for testing',
  377. # binary string representing the tree object ID
  378. tree,
  379. # list of binary strings representing parents of the new commit
  380. []
  381. )
  382. first_commit = repo.revparse_single('HEAD')
  383. refname = 'refs/heads/master:refs/heads/master'
  384. ori_remote = repo.remotes[0]
  385. PagureRepo.push(ori_remote, refname)
  386. # Edit the sources file again
  387. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  388. stream.write('foo\n bar\nbaz\n boose')
  389. repo.index.add('sources')
  390. repo.index.write()
  391. # Commits the files added
  392. tree = repo.index.write_tree()
  393. author = pygit2.Signature(
  394. 'Alice Author', 'alice@authors.tld')
  395. committer = pygit2.Signature(
  396. 'Cecil Committer', 'cecil@committers.tld')
  397. repo.create_commit(
  398. 'refs/heads/feature', # the name of the reference to update
  399. author,
  400. committer,
  401. 'Add baz and boose to the sources\n\n There are more objects to '
  402. 'consider',
  403. # binary string representing the tree object ID
  404. tree,
  405. # list of binary strings representing parents of the new commit
  406. [first_commit.oid.hex]
  407. )
  408. second_commit = repo.revparse_single('HEAD')
  409. refname = 'refs/heads/feature:refs/heads/feature'
  410. ori_remote = repo.remotes[0]
  411. PagureRepo.push(ori_remote, refname)
  412. # Create a PR for these changes
  413. tests.create_projects(self.session)
  414. project = pagure.lib.get_authorized_project(self.session, 'test')
  415. req = pagure.lib.new_pull_request(
  416. session=self.session,
  417. repo_from=project,
  418. branch_from='feature',
  419. repo_to=project,
  420. branch_to='master',
  421. title='PR from the feature branch',
  422. user='pingou',
  423. requestfolder=None,
  424. )
  425. self.session.commit()
  426. self.assertEqual(req.id, 1)
  427. self.assertEqual(req.title, 'PR from the feature branch')
  428. # Check if the PR can be merged
  429. data = {
  430. 'objid': 'blah',
  431. }
  432. # Missing CSRF
  433. output = self.app.post('/pv/pull-request/merge', data=data)
  434. self.assertEqual(output.status_code, 400)
  435. user = tests.FakeUser()
  436. user.username = 'pingou'
  437. with tests.user_set(self.app.application, user):
  438. output = self.app.get('/test/adduser')
  439. csrf_token = output.get_data(as_text=True).split(
  440. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  441. # Missing request identifier
  442. data = {
  443. 'csrf_token': csrf_token,
  444. }
  445. output = self.app.post('/pv/pull-request/merge', data=data)
  446. self.assertEqual(output.status_code, 404)
  447. # With all the desired information
  448. project = pagure.lib.get_authorized_project(self.session, 'test')
  449. data = {
  450. 'csrf_token': csrf_token,
  451. 'requestid': project.requests[0].uid,
  452. }
  453. output = self.app.post('/pv/pull-request/merge', data=data)
  454. self.assertEqual(output.status_code, 200)
  455. exp = {
  456. "code": "FFORWARD",
  457. "message": "The pull-request can be merged and fast-forwarded",
  458. "short_code": "Ok"
  459. }
  460. js_data = json.loads(output.get_data(as_text=True))
  461. self.assertDictEqual(js_data, exp)
  462. @patch('pagure.lib.notify.send_email')
  463. def test_mergeable_request_pull_no_change(self, send_email):
  464. """ Test the mergeable_request_pull endpoint when there are no
  465. changes to merge.
  466. """
  467. send_email.return_value = True
  468. # Create a git repo to play with
  469. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  470. self.assertFalse(os.path.exists(gitrepo))
  471. os.makedirs(gitrepo)
  472. repo = pygit2.init_repository(gitrepo)
  473. # Create a file in that git repo
  474. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  475. stream.write('foo\n bar')
  476. repo.index.add('sources')
  477. repo.index.write()
  478. # Commits the files added
  479. tree = repo.index.write_tree()
  480. author = pygit2.Signature(
  481. 'Alice Author', 'alice@authors.tld')
  482. committer = pygit2.Signature(
  483. 'Cecil Committer', 'cecil@committers.tld')
  484. repo.create_commit(
  485. 'refs/heads/master', # the name of the reference to update
  486. author,
  487. committer,
  488. 'Add sources file for testing',
  489. # binary string representing the tree object ID
  490. tree,
  491. # list of binary strings representing parents of the new commit
  492. []
  493. )
  494. first_commit = repo.revparse_single('HEAD')
  495. # Edit the sources file again
  496. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  497. stream.write('foo\n bar\nbaz\n boose')
  498. repo.index.add('sources')
  499. repo.index.write()
  500. # Commits the files added
  501. tree = repo.index.write_tree()
  502. author = pygit2.Signature(
  503. 'Alice Author', 'alice@authors.tld')
  504. committer = pygit2.Signature(
  505. 'Cecil Committer', 'cecil@committers.tld')
  506. repo.create_commit(
  507. 'refs/heads/master', # the name of the reference to update
  508. author,
  509. committer,
  510. 'Add baz and boose to the sources\n\n There are more objects to '
  511. 'consider',
  512. # binary string representing the tree object ID
  513. tree,
  514. # list of binary strings representing parents of the new commit
  515. [first_commit.oid.hex]
  516. )
  517. second_commit = repo.revparse_single('HEAD')
  518. # Create a PR for these changes
  519. tests.create_projects(self.session)
  520. project = pagure.lib.get_authorized_project(self.session, 'test')
  521. req = pagure.lib.new_pull_request(
  522. session=self.session,
  523. repo_from=project,
  524. branch_from='master',
  525. repo_to=project,
  526. branch_to='master',
  527. title='PR from the feature branch',
  528. user='pingou',
  529. requestfolder=None,
  530. )
  531. self.session.commit()
  532. self.assertEqual(req.id, 1)
  533. self.assertEqual(req.title, 'PR from the feature branch')
  534. # Check if the PR can be merged
  535. data = {
  536. 'objid': 'blah',
  537. }
  538. # Missing CSRF
  539. output = self.app.post('/pv/pull-request/merge', data=data)
  540. self.assertEqual(output.status_code, 400)
  541. user = tests.FakeUser()
  542. user.username = 'pingou'
  543. with tests.user_set(self.app.application, user):
  544. output = self.app.get('/test/adduser')
  545. csrf_token = output.get_data(as_text=True).split(
  546. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  547. # Missing request identifier
  548. data = {
  549. 'csrf_token': csrf_token,
  550. }
  551. output = self.app.post('/pv/pull-request/merge', data=data)
  552. self.assertEqual(output.status_code, 404)
  553. # With all the desired information
  554. project = pagure.lib.get_authorized_project(self.session, 'test')
  555. data = {
  556. 'csrf_token': csrf_token,
  557. 'requestid': project.requests[0].uid,
  558. }
  559. output = self.app.post('/pv/pull-request/merge', data=data)
  560. self.assertEqual(output.status_code, 200)
  561. exp = {
  562. "code": "NO_CHANGE",
  563. "message": "Nothing to change, git is up to date",
  564. "short_code": "No changes"
  565. }
  566. js_data = json.loads(output.get_data(as_text=True))
  567. self.assertDictEqual(js_data, exp)
  568. @patch('pagure.lib.notify.send_email')
  569. def test_mergeable_request_pull_merge(self, send_email):
  570. """ Test the mergeable_request_pull endpoint when the changes can
  571. be merged with a merge commit.
  572. """
  573. send_email.return_value = True
  574. # Create a git repo to play with
  575. origgitrepo = os.path.join(self.path, 'repos', 'test.git')
  576. self.assertFalse(os.path.exists(origgitrepo))
  577. os.makedirs(origgitrepo)
  578. orig_repo = pygit2.init_repository(origgitrepo, bare=True)
  579. os.makedirs(os.path.join(self.path, 'repos_tmp'))
  580. gitrepo = os.path.join(self.path, 'repos_tmp', 'test.git')
  581. repo = pygit2.clone_repository(origgitrepo, gitrepo)
  582. # Create a file in that git repo
  583. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  584. stream.write('foo\n bar')
  585. repo.index.add('sources')
  586. repo.index.write()
  587. # Commits the files added
  588. tree = repo.index.write_tree()
  589. author = pygit2.Signature(
  590. 'Alice Author', 'alice@authors.tld')
  591. committer = pygit2.Signature(
  592. 'Cecil Committer', 'cecil@committers.tld')
  593. repo.create_commit(
  594. 'refs/heads/master', # the name of the reference to update
  595. author,
  596. committer,
  597. 'Add sources file for testing',
  598. # binary string representing the tree object ID
  599. tree,
  600. # list of binary strings representing parents of the new commit
  601. []
  602. )
  603. first_commit = repo.revparse_single('HEAD')
  604. refname = 'refs/heads/master:refs/heads/master'
  605. ori_remote = repo.remotes[0]
  606. PagureRepo.push(ori_remote, refname)
  607. # Edit the sources file again
  608. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  609. stream.write('foo\n bar\nbaz\n boose')
  610. repo.index.add('sources')
  611. repo.index.write()
  612. # Commits the files added
  613. tree = repo.index.write_tree()
  614. author = pygit2.Signature(
  615. 'Alice Author', 'alice@authors.tld')
  616. committer = pygit2.Signature(
  617. 'Cecil Committer', 'cecil@committers.tld')
  618. repo.create_commit(
  619. 'refs/heads/feature', # the name of the reference to update
  620. author,
  621. committer,
  622. 'Add baz and boose to the sources\n\n There are more objects to '
  623. 'consider',
  624. # binary string representing the tree object ID
  625. tree,
  626. # list of binary strings representing parents of the new commit
  627. [first_commit.oid.hex]
  628. )
  629. refname = 'refs/heads/feature:refs/heads/feature'
  630. ori_remote = repo.remotes[0]
  631. PagureRepo.push(ori_remote, refname)
  632. # Create another file in the master branch
  633. with open(os.path.join(gitrepo, '.gitignore'), 'w') as stream:
  634. stream.write('*~')
  635. repo.index.add('.gitignore')
  636. repo.index.write()
  637. # Commits the files added
  638. tree = repo.index.write_tree()
  639. author = pygit2.Signature(
  640. 'Alice Author', 'alice@authors.tld')
  641. committer = pygit2.Signature(
  642. 'Cecil Committer', 'cecil@committers.tld')
  643. repo.create_commit(
  644. 'refs/heads/master', # the name of the reference to update
  645. author,
  646. committer,
  647. 'Add .gitignore file for testing',
  648. # binary string representing the tree object ID
  649. tree,
  650. # list of binary strings representing parents of the new commit
  651. [first_commit.oid.hex]
  652. )
  653. refname = 'refs/heads/master:refs/heads/master'
  654. ori_remote = repo.remotes[0]
  655. PagureRepo.push(ori_remote, refname)
  656. # Create a PR for these changes
  657. tests.create_projects(self.session)
  658. project = pagure.lib.get_authorized_project(self.session, 'test')
  659. req = pagure.lib.new_pull_request(
  660. session=self.session,
  661. repo_from=project,
  662. branch_from='feature',
  663. repo_to=project,
  664. branch_to='master',
  665. title='PR from the feature branch',
  666. user='pingou',
  667. requestfolder=None,
  668. )
  669. self.session.commit()
  670. self.assertEqual(req.id, 1)
  671. self.assertEqual(req.title, 'PR from the feature branch')
  672. # Check if the PR can be merged
  673. data = {}
  674. # Missing CSRF
  675. output = self.app.post('/pv/pull-request/merge', data=data)
  676. self.assertEqual(output.status_code, 400)
  677. user = tests.FakeUser()
  678. user.username = 'pingou'
  679. with tests.user_set(self.app.application, user):
  680. output = self.app.get('/test/adduser')
  681. csrf_token = output.get_data(as_text=True).split(
  682. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  683. # Missing request identifier
  684. data = {
  685. 'csrf_token': csrf_token,
  686. }
  687. output = self.app.post('/pv/pull-request/merge', data=data)
  688. self.assertEqual(output.status_code, 404)
  689. # With all the desired information
  690. project = pagure.lib.get_authorized_project(self.session, 'test')
  691. data = {
  692. 'csrf_token': csrf_token,
  693. 'requestid': project.requests[0].uid,
  694. }
  695. output = self.app.post('/pv/pull-request/merge', data=data)
  696. self.assertEqual(output.status_code, 200)
  697. exp = {
  698. "code": "MERGE",
  699. "message": "The pull-request can be merged with a merge commit",
  700. "short_code": "With merge"
  701. }
  702. js_data = json.loads(output.get_data(as_text=True))
  703. self.assertDictEqual(js_data, exp)
  704. @patch('pagure.lib.notify.send_email')
  705. def test_mergeable_request_pull_conflicts(self, send_email):
  706. """ Test the mergeable_request_pull endpoint when the changes cannot
  707. be merged due to conflicts.
  708. """
  709. send_email.return_value = True
  710. # Create a git repo to play with
  711. origgitrepo = os.path.join(self.path, 'repos', 'test.git')
  712. self.assertFalse(os.path.exists(origgitrepo))
  713. os.makedirs(origgitrepo)
  714. orig_repo = pygit2.init_repository(origgitrepo, bare=True)
  715. os.makedirs(os.path.join(self.path, 'repos_tmp'))
  716. gitrepo = os.path.join(self.path, 'repos_tmp', 'test.git')
  717. repo = pygit2.clone_repository(origgitrepo, gitrepo)
  718. # Create a file in that git repo
  719. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  720. stream.write('foo\n bar')
  721. repo.index.add('sources')
  722. repo.index.write()
  723. # Commits the files added
  724. tree = repo.index.write_tree()
  725. author = pygit2.Signature(
  726. 'Alice Author', 'alice@authors.tld')
  727. committer = pygit2.Signature(
  728. 'Cecil Committer', 'cecil@committers.tld')
  729. repo.create_commit(
  730. 'refs/heads/master', # the name of the reference to update
  731. author,
  732. committer,
  733. 'Add sources file for testing',
  734. # binary string representing the tree object ID
  735. tree,
  736. # list of binary strings representing parents of the new commit
  737. []
  738. )
  739. first_commit = repo.revparse_single('HEAD')
  740. refname = 'refs/heads/master:refs/heads/master'
  741. ori_remote = repo.remotes[0]
  742. PagureRepo.push(ori_remote, refname)
  743. # Edit the sources file again
  744. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  745. stream.write('foo\n bar\nbaz\n boose')
  746. repo.index.add('sources')
  747. repo.index.write()
  748. # Commits the files added
  749. tree = repo.index.write_tree()
  750. author = pygit2.Signature(
  751. 'Alice Author', 'alice@authors.tld')
  752. committer = pygit2.Signature(
  753. 'Cecil Committer', 'cecil@committers.tld')
  754. repo.create_commit(
  755. 'refs/heads/feature', # the name of the reference to update
  756. author,
  757. committer,
  758. 'Add baz and boose to the sources\n\n There are more objects to '
  759. 'consider',
  760. # binary string representing the tree object ID
  761. tree,
  762. # list of binary strings representing parents of the new commit
  763. [first_commit.oid.hex]
  764. )
  765. refname = 'refs/heads/feature:refs/heads/feature'
  766. ori_remote = repo.remotes[0]
  767. PagureRepo.push(ori_remote, refname)
  768. # Create another file in the master branch
  769. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  770. stream.write('foo\n bar\nbaz\n')
  771. repo.index.add('sources')
  772. repo.index.write()
  773. # Commits the files added
  774. tree = repo.index.write_tree()
  775. author = pygit2.Signature(
  776. 'Alice Author', 'alice@authors.tld')
  777. committer = pygit2.Signature(
  778. 'Cecil Committer', 'cecil@committers.tld')
  779. repo.create_commit(
  780. 'refs/heads/master', # the name of the reference to update
  781. author,
  782. committer,
  783. 'Add .gitignore file for testing',
  784. # binary string representing the tree object ID
  785. tree,
  786. # list of binary strings representing parents of the new commit
  787. [first_commit.oid.hex]
  788. )
  789. refname = 'refs/heads/master:refs/heads/master'
  790. ori_remote = repo.remotes[0]
  791. PagureRepo.push(ori_remote, refname)
  792. # Create a PR for these changes
  793. tests.create_projects(self.session)
  794. project = pagure.lib.get_authorized_project(self.session, 'test')
  795. req = pagure.lib.new_pull_request(
  796. session=self.session,
  797. repo_from=project,
  798. branch_from='feature',
  799. repo_to=project,
  800. branch_to='master',
  801. title='PR from the feature branch',
  802. user='pingou',
  803. requestfolder=None,
  804. )
  805. self.session.commit()
  806. self.assertEqual(req.id, 1)
  807. self.assertEqual(req.title, 'PR from the feature branch')
  808. # Check if the PR can be merged
  809. data = {}
  810. # Missing CSRF
  811. output = self.app.post('/pv/pull-request/merge', data=data)
  812. self.assertEqual(output.status_code, 400)
  813. user = tests.FakeUser()
  814. user.username = 'pingou'
  815. with tests.user_set(self.app.application, user):
  816. output = self.app.get('/test/adduser')
  817. csrf_token = output.get_data(as_text=True).split(
  818. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  819. # Missing request identifier
  820. data = {
  821. 'csrf_token': csrf_token,
  822. }
  823. output = self.app.post('/pv/pull-request/merge', data=data)
  824. self.assertEqual(output.status_code, 404)
  825. # With all the desired information
  826. project = pagure.lib.get_authorized_project(self.session, 'test')
  827. data = {
  828. 'csrf_token': csrf_token,
  829. 'requestid': project.requests[0].uid,
  830. }
  831. output = self.app.post('/pv/pull-request/merge', data=data)
  832. self.assertEqual(output.status_code, 200)
  833. exp = {
  834. "code": "CONFLICTS",
  835. "message": "The pull-request cannot be merged due to conflicts",
  836. "short_code": "Conflicts"
  837. }
  838. js_data = json.loads(output.get_data(as_text=True))
  839. self.assertDictEqual(js_data, exp)
  840. def test_get_branches_of_commit(self):
  841. ''' Test the get_branches_of_commit from the internal API. '''
  842. tests.create_projects(self.session)
  843. tests.create_projects_git(os.path.join(self.path, 'repos'))
  844. user = tests.FakeUser()
  845. user.username = 'pingou'
  846. with tests.user_set(self.app.application, user):
  847. output = self.app.get('/test/adduser')
  848. self.assertEqual(output.status_code, 200)
  849. csrf_token = output.get_data(as_text=True).split(
  850. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  851. # No CSRF token
  852. data = {
  853. 'repo': 'fakerepo',
  854. 'commit_id': 'foo',
  855. }
  856. output = self.app.post('/pv/branches/commit/', data=data)
  857. self.assertEqual(output.status_code, 400)
  858. js_data = json.loads(output.get_data(as_text=True))
  859. self.assertDictEqual(
  860. js_data,
  861. {'code': 'ERROR', 'message': 'Invalid input submitted'}
  862. )
  863. # Invalid repo
  864. data = {
  865. 'repo': 'fakerepo',
  866. 'commit_id': 'foo',
  867. 'csrf_token': csrf_token,
  868. }
  869. output = self.app.post('/pv/branches/commit/', data=data)
  870. self.assertEqual(output.status_code, 404)
  871. js_data = json.loads(output.get_data(as_text=True))
  872. self.assertDictEqual(
  873. js_data,
  874. {
  875. 'code': 'ERROR',
  876. 'message': 'No repo found with the information provided'
  877. }
  878. )
  879. # Rigth repo, no commit
  880. data = {
  881. 'repo': 'test',
  882. 'csrf_token': csrf_token,
  883. }
  884. output = self.app.post('/pv/branches/commit/', data=data)
  885. self.assertEqual(output.status_code, 400)
  886. js_data = json.loads(output.get_data(as_text=True))
  887. self.assertDictEqual(
  888. js_data,
  889. {'code': 'ERROR', 'message': 'No commit id submitted'}
  890. )
  891. # Request is fine, but git repo doesn't exist
  892. item = pagure.lib.model.Project(
  893. user_id=1, # pingou
  894. name='test20',
  895. description='test project #20',
  896. hook_token='aaabbbhhh',
  897. )
  898. self.session.add(item)
  899. self.session.commit()
  900. data = {
  901. 'repo': 'test20',
  902. 'commit_id': 'foo',
  903. 'csrf_token': csrf_token,
  904. }
  905. output = self.app.post('/pv/branches/commit/', data=data)
  906. self.assertEqual(output.status_code, 404)
  907. js_data = json.loads(output.get_data(as_text=True))
  908. self.assertDictEqual(
  909. js_data,
  910. {
  911. 'code': 'ERROR',
  912. 'message': 'No git repo found with the information provided'
  913. }
  914. )
  915. # Create a git repo to play with
  916. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  917. self.assertTrue(os.path.exists(gitrepo))
  918. repo = pygit2.Repository(gitrepo)
  919. # Create a file in that git repo
  920. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  921. stream.write('foo\n bar')
  922. repo.index.add('sources')
  923. repo.index.write()
  924. # Commits the files added
  925. tree = repo.index.write_tree()
  926. author = pygit2.Signature(
  927. 'Alice Author', 'alice@authors.tld')
  928. committer = pygit2.Signature(
  929. 'Cecil Committer', 'cecil@committers.tld')
  930. repo.create_commit(
  931. 'refs/heads/master', # the name of the reference to update
  932. author,
  933. committer,
  934. 'Add sources file for testing',
  935. # binary string representing the tree object ID
  936. tree,
  937. # list of binary strings representing parents of the new commit
  938. []
  939. )
  940. first_commit = repo.revparse_single('HEAD')
  941. # Edit the sources file again
  942. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  943. stream.write('foo\n bar\nbaz\n boose')
  944. repo.index.add('sources')
  945. repo.index.write()
  946. # Commits the files added
  947. tree = repo.index.write_tree()
  948. author = pygit2.Signature(
  949. 'Alice Author', 'alice@authors.tld')
  950. committer = pygit2.Signature(
  951. 'Cecil Committer', 'cecil@committers.tld')
  952. repo.create_commit(
  953. 'refs/heads/feature', # the name of the reference to update
  954. author,
  955. committer,
  956. 'Add baz and boose to the sources\n\n There are more objects to '
  957. 'consider',
  958. # binary string representing the tree object ID
  959. tree,
  960. # list of binary strings representing parents of the new commit
  961. [first_commit.oid.hex]
  962. )
  963. # Create another file in the master branch
  964. with open(os.path.join(gitrepo, '.gitignore'), 'w') as stream:
  965. stream.write('*~')
  966. repo.index.add('.gitignore')
  967. repo.index.write()
  968. # Commits the files added
  969. tree = repo.index.write_tree()
  970. author = pygit2.Signature(
  971. 'Alice Author', 'alice@authors.tld')
  972. committer = pygit2.Signature(
  973. 'Cecil Committer', 'cecil@committers.tld')
  974. commit_hash = repo.create_commit(
  975. 'refs/heads/feature_branch', # the name of the reference to update
  976. author,
  977. committer,
  978. 'Add .gitignore file for testing',
  979. # binary string representing the tree object ID
  980. tree,
  981. # list of binary strings representing parents of the new commit
  982. [first_commit.oid.hex]
  983. )
  984. # All good but the commit id
  985. data = {
  986. 'repo': 'test',
  987. 'commit_id': 'foo',
  988. 'csrf_token': csrf_token,
  989. }
  990. output = self.app.post('/pv/branches/commit/', data=data)
  991. self.assertEqual(output.status_code, 404)
  992. js_data = json.loads(output.get_data(as_text=True))
  993. self.assertDictEqual(
  994. js_data,
  995. {
  996. 'code': 'ERROR',
  997. 'message': 'This commit could not be found in this repo'
  998. }
  999. )
  1000. # All good
  1001. data = {
  1002. 'repo': 'test',
  1003. 'commit_id': commit_hash,
  1004. 'csrf_token': csrf_token,
  1005. }
  1006. output = self.app.post('/pv/branches/commit/', data=data)
  1007. self.assertEqual(output.status_code, 200)
  1008. js_data = json.loads(output.get_data(as_text=True))
  1009. self.assertDictEqual(
  1010. js_data,
  1011. {
  1012. 'code': 'OK',
  1013. 'branches': ['feature_branch'],
  1014. }
  1015. )
  1016. def test_get_branches_of_commit_with_unrelated_branches(self):
  1017. ''' Test the get_branches_of_commit from the internal API. '''
  1018. tests.create_projects(self.session)
  1019. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1020. user = tests.FakeUser(username='pingou')
  1021. with tests.user_set(self.app.application, user):
  1022. csrf_token = self.get_csrf()
  1023. # Create a git repo to play with
  1024. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1025. self.assertTrue(os.path.exists(gitrepo))
  1026. repo = pygit2.Repository(gitrepo)
  1027. # Create a file in that git repo
  1028. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  1029. stream.write('foo\n bar')
  1030. repo.index.add('sources')
  1031. repo.index.write()
  1032. # Commits the files added
  1033. tree = repo.index.write_tree()
  1034. author = pygit2.Signature(
  1035. 'Alice Author', 'alice@authors.tld')
  1036. committer = pygit2.Signature(
  1037. 'Cecil Committer', 'cecil@committers.tld')
  1038. repo.create_commit(
  1039. 'refs/heads/master', # the name of the reference to update
  1040. author,
  1041. committer,
  1042. 'Add sources file for testing',
  1043. # binary string representing the tree object ID
  1044. tree,
  1045. # list of binary strings representing parents of the new commit
  1046. []
  1047. )
  1048. first_commit = repo.revparse_single('HEAD')
  1049. # Edit the sources file again
  1050. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  1051. stream.write('foo\n bar\nbaz\n boose')
  1052. repo.index.add('sources')
  1053. repo.index.write()
  1054. # Commits the files added, but unrelated with the first commit
  1055. tree = repo.index.write_tree()
  1056. author = pygit2.Signature(
  1057. 'Alice Author', 'alice@authors.tld')
  1058. committer = pygit2.Signature(
  1059. 'Cecil Committer', 'cecil@committers.tld')
  1060. commit = repo.create_commit(
  1061. 'refs/heads/feature', # the name of the reference to update
  1062. author,
  1063. committer,
  1064. 'Add baz and boose to the sources\n\n There are more objects to '
  1065. 'consider',
  1066. # binary string representing the tree object ID
  1067. tree,
  1068. # list of binary strings representing parents of the new commit
  1069. []
  1070. )
  1071. commit_hash = commit.hex
  1072. # All good
  1073. data = {
  1074. 'repo': 'test',
  1075. 'commit_id': commit_hash,
  1076. 'csrf_token': csrf_token,
  1077. }
  1078. output = self.app.post('/pv/branches/commit/', data=data)
  1079. self.assertEqual(output.status_code, 200)
  1080. js_data = json.loads(output.get_data(as_text=True))
  1081. self.assertDictEqual(
  1082. js_data,
  1083. {
  1084. u'code': u'OK',
  1085. u'branches': ['feature'],
  1086. }
  1087. )
  1088. def test_get_branches_head(self):
  1089. ''' Test the get_branches_head from the internal API. '''
  1090. tests.create_projects(self.session)
  1091. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1092. user = tests.FakeUser()
  1093. user.username = 'pingou'
  1094. with tests.user_set(self.app.application, user):
  1095. csrf_token = self.get_csrf()
  1096. # No CSRF token
  1097. data = {
  1098. 'repo': 'fakerepo',
  1099. }
  1100. output = self.app.post('/pv/branches/heads/', data=data)
  1101. self.assertEqual(output.status_code, 400)
  1102. js_data = json.loads(output.get_data(as_text=True))
  1103. self.assertDictEqual(
  1104. js_data,
  1105. {'code': 'ERROR', 'message': 'Invalid input submitted'}
  1106. )
  1107. # Invalid repo
  1108. data = {
  1109. 'repo': 'fakerepo',
  1110. 'commit_id': 'foo',
  1111. 'csrf_token': csrf_token,
  1112. }
  1113. output = self.app.post('/pv/branches/heads/', data=data)
  1114. self.assertEqual(output.status_code, 404)
  1115. js_data = json.loads(output.get_data(as_text=True))
  1116. self.assertDictEqual(
  1117. js_data,
  1118. {
  1119. 'code': 'ERROR',
  1120. 'message': 'No repo found with the information provided'
  1121. }
  1122. )
  1123. # Rigth repo, no commit
  1124. data = {
  1125. 'repo': 'test',
  1126. 'csrf_token': csrf_token,
  1127. }
  1128. output = self.app.post('/pv/branches/heads/', data=data)
  1129. self.assertEqual(output.status_code, 200)
  1130. js_data = json.loads(output.get_data(as_text=True))
  1131. self.assertDictEqual(
  1132. js_data,
  1133. {"branches": {}, "code": "OK", "heads": {}}
  1134. )
  1135. # Request is fine, but git repo doesn't exist
  1136. item = pagure.lib.model.Project(
  1137. user_id=1, # pingou
  1138. name='test20',
  1139. description='test project #20',
  1140. hook_token='aaabbbhhh',
  1141. )
  1142. self.session.add(item)
  1143. self.session.commit()
  1144. data = {
  1145. 'repo': 'test20',
  1146. 'csrf_token': csrf_token,
  1147. }
  1148. output = self.app.post('/pv/branches/heads/', data=data)
  1149. self.assertEqual(output.status_code, 404)
  1150. js_data = json.loads(output.get_data(as_text=True))
  1151. self.assertDictEqual(
  1152. js_data,
  1153. {
  1154. 'code': 'ERROR',
  1155. 'message': 'No git repo found with the information provided'
  1156. }
  1157. )
  1158. # Create a git repo to play with
  1159. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1160. self.assertTrue(os.path.exists(gitrepo))
  1161. repo = pygit2.Repository(gitrepo)
  1162. # Create a file in that git repo
  1163. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  1164. stream.write('foo\n bar')
  1165. repo.index.add('sources')
  1166. repo.index.write()
  1167. # Commits the files added
  1168. tree = repo.index.write_tree()
  1169. author = pygit2.Signature(
  1170. 'Alice Author', 'alice@authors.tld')
  1171. committer = pygit2.Signature(
  1172. 'Cecil Committer', 'cecil@committers.tld')
  1173. repo.create_commit(
  1174. 'refs/heads/master', # the name of the reference to update
  1175. author,
  1176. committer,
  1177. 'Add sources file for testing',
  1178. # binary string representing the tree object ID
  1179. tree,
  1180. # list of binary strings representing parents of the new commit
  1181. []
  1182. )
  1183. first_commit = repo.revparse_single('HEAD')
  1184. # Edit the sources file again
  1185. with open(os.path.join(gitrepo, 'sources'), 'w') as stream:
  1186. stream.write('foo\n bar\nbaz\n boose')
  1187. repo.index.add('sources')
  1188. repo.index.write()
  1189. # Commits the files added
  1190. tree = repo.index.write_tree()
  1191. author = pygit2.Signature(
  1192. 'Alice Author', 'alice@authors.tld')
  1193. committer = pygit2.Signature(
  1194. 'Cecil Committer', 'cecil@committers.tld')
  1195. repo.create_commit(
  1196. 'refs/heads/feature', # the name of the reference to update
  1197. author,
  1198. committer,
  1199. 'Add baz and boose to the sources\n\n There are more objects to '
  1200. 'consider',
  1201. # binary string representing the tree object ID
  1202. tree,
  1203. # list of binary strings representing parents of the new commit
  1204. [first_commit.oid.hex]
  1205. )
  1206. # Create another file in the master branch
  1207. with open(os.path.join(gitrepo, '.gitignore'), 'w') as stream:
  1208. stream.write('*~')
  1209. repo.index.add('.gitignore')
  1210. repo.index.write()
  1211. # Commits the files added
  1212. tree = repo.index.write_tree()
  1213. author = pygit2.Signature(
  1214. 'Alice Author', 'alice@authors.tld')
  1215. committer = pygit2.Signature(
  1216. 'Cecil Committer', 'cecil@committers.tld')
  1217. commit_hash = repo.create_commit(
  1218. 'refs/heads/feature_branch', # the name of the reference to update
  1219. author,
  1220. committer,
  1221. 'Add .gitignore file for testing',
  1222. # binary string representing the tree object ID
  1223. tree,
  1224. # list of binary strings representing parents of the new commit
  1225. [first_commit.oid.hex]
  1226. )
  1227. # All good
  1228. data = {
  1229. 'repo': 'test',
  1230. 'csrf_token': csrf_token,
  1231. }
  1232. output = self.app.post('/pv/branches/heads/', data=data)
  1233. self.assertEqual(output.status_code, 200)
  1234. js_data = json.loads(output.get_data(as_text=True))
  1235. # We can't test the content since the commit hash will change all
  1236. # the time, so let's just check the structure
  1237. self.assertEqual(
  1238. sorted(js_data.keys()), ['branches', 'code', 'heads'])
  1239. self.assertEqual(js_data['code'], 'OK')
  1240. self.assertEqual(len(js_data['heads']), 3)
  1241. self.assertEqual(len(js_data['branches']), 3)
  1242. def test_get_stats_commits_no_token(self):
  1243. ''' Test the get_stats_commits from the internal API. '''
  1244. # No CSRF token
  1245. data = {
  1246. 'repo': 'fakerepo',
  1247. }
  1248. output = self.app.post('/pv/stats/commits/authors', data=data)
  1249. self.assertEqual(output.status_code, 400)
  1250. js_data = json.loads(output.get_data(as_text=True))
  1251. self.assertDictEqual(
  1252. js_data,
  1253. {'code': 'ERROR', 'message': 'Invalid input submitted'}
  1254. )
  1255. def test_get_stats_commits_invalid_repo(self):
  1256. ''' Test the get_stats_commits from the internal API. '''
  1257. user = tests.FakeUser()
  1258. user.username = 'pingou'
  1259. with tests.user_set(self.app.application, user):
  1260. csrf_token = self.get_csrf()
  1261. # Invalid repo
  1262. data = {
  1263. 'repo': 'fakerepo',
  1264. 'csrf_token': csrf_token,
  1265. }
  1266. output = self.app.post('/pv/stats/commits/authors', data=data)
  1267. self.assertEqual(output.status_code, 404)
  1268. js_data = json.loads(output.get_data(as_text=True))
  1269. self.assertDictEqual(
  1270. js_data,
  1271. {'code': 'ERROR',
  1272. 'message': 'No repo found with the information provided'}
  1273. )
  1274. def test_get_stats_commits_empty_git(self):
  1275. ''' Test the get_stats_commits from the internal API. '''
  1276. tests.create_projects(self.session)
  1277. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1278. user = tests.FakeUser()
  1279. user.username = 'pingou'
  1280. with tests.user_set(self.app.application, user):
  1281. csrf_token = self.get_csrf()
  1282. # No content in git
  1283. data = {
  1284. 'repo': 'test',
  1285. 'csrf_token': csrf_token,
  1286. }
  1287. output = self.app.post('/pv/stats/commits/authors', data=data)
  1288. self.assertEqual(output.status_code, 200)
  1289. js_data = json.loads(output.get_data(as_text=True))
  1290. self.assertEqual(
  1291. sorted(js_data.keys()),
  1292. ['code', 'message', 'task_id', 'url']
  1293. )
  1294. self.assertEqual(js_data['code'], 'OK')
  1295. self.assertEqual(js_data['message'], 'Stats asked')
  1296. self.assertTrue(js_data['url'].startswith('/pv/task/'))
  1297. output = self.app.get(js_data['url'])
  1298. js_data2 = json.loads(output.get_data(as_text=True))
  1299. self.assertTrue(
  1300. js_data2 in [
  1301. {'results': "reference 'refs/heads/master' not found"},
  1302. {'results': "Reference 'refs/heads/master' not found"}
  1303. ]
  1304. )
  1305. def test_get_stats_commits_git_populated(self):
  1306. ''' Test the get_stats_commits from the internal API. '''
  1307. tests.create_projects(self.session)
  1308. tests.create_projects_git(
  1309. os.path.join(self.path, 'repos'), bare=True)
  1310. tests.add_content_git_repo(
  1311. os.path.join(self.path, 'repos', 'test.git'))
  1312. user = tests.FakeUser()
  1313. user.username = 'pingou'
  1314. with tests.user_set(self.app.application, user):
  1315. csrf_token = self.get_csrf()
  1316. # Content in git
  1317. data = {
  1318. 'repo': 'test',
  1319. 'csrf_token': csrf_token,
  1320. }
  1321. output = self.app.post('/pv/stats/commits/authors', data=data)
  1322. self.assertEqual(output.status_code, 200)
  1323. js_data = json.loads(output.get_data(as_text=True))
  1324. self.assertEqual(
  1325. sorted(js_data.keys()),
  1326. ['code', 'message', 'task_id', 'url']
  1327. )
  1328. self.assertEqual(js_data['code'], 'OK')
  1329. self.assertEqual(js_data['message'], 'Stats asked')
  1330. self.assertTrue(js_data['url'].startswith('/pv/task/'))
  1331. output = self.app.get(js_data['url'])
  1332. while output.status_code == 418:
  1333. time.sleep(0.5)
  1334. output = self.app.get(js_data['url'])
  1335. js_data2 = json.loads(output.get_data(as_text=True))
  1336. self.assertTrue(js_data2['results'][3] > 1509110062)
  1337. js_data2['results'][3] = 1509110062
  1338. self.assertDictEqual(
  1339. js_data2,
  1340. {'results': [
  1341. 2,
  1342. [[2, [['Alice Author', 'alice@authors.tld']]]],
  1343. 1,
  1344. 1509110062
  1345. ]
  1346. }
  1347. )
  1348. def test_get_stats_commits_trend_no_token(self):
  1349. ''' Test the get_stats_commits_trend from the internal API. '''
  1350. # No CSRF token
  1351. data = {
  1352. 'repo': 'fakerepo',
  1353. }
  1354. output = self.app.post('/pv/stats/commits/trend', data=data)
  1355. self.assertEqual(output.status_code, 400)
  1356. js_data = json.loads(output.get_data(as_text=True))
  1357. self.assertDictEqual(
  1358. js_data,
  1359. {'code': 'ERROR', 'message': 'Invalid input submitted'}
  1360. )
  1361. def test_get_stats_commits_trend_invalid_repo(self):
  1362. """ Test the get_stats_commits_trend from the internal API. """
  1363. user = tests.FakeUser()
  1364. user.username = 'pingou'
  1365. with tests.user_set(self.app.application, user):
  1366. csrf_token = self.get_csrf()
  1367. # Invalid repo
  1368. data = {
  1369. 'repo': 'fakerepo',
  1370. 'csrf_token': csrf_token,
  1371. }
  1372. output = self.app.post('/pv/stats/commits/trend', data=data)
  1373. self.assertEqual(output.status_code, 404)
  1374. js_data = json.loads(output.get_data(as_text=True))
  1375. self.assertDictEqual(
  1376. js_data,
  1377. {'code': 'ERROR',
  1378. 'message': 'No repo found with the information provided'}
  1379. )
  1380. def test_get_stats_commits_trend_empty_git(self):
  1381. ''' Test the get_stats_commits_trend from the internal API. '''
  1382. tests.create_projects(self.session)
  1383. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1384. user = tests.FakeUser()
  1385. user.username = 'pingou'
  1386. with tests.user_set(self.app.application, user):
  1387. csrf_token = self.get_csrf()
  1388. # No content in git
  1389. data = {
  1390. 'repo': 'test',
  1391. 'csrf_token': csrf_token,
  1392. }
  1393. output = self.app.post('/pv/stats/commits/trend', data=data)
  1394. self.assertEqual(output.status_code, 200)
  1395. js_data = json.loads(output.get_data(as_text=True))
  1396. self.assertEqual(
  1397. sorted(js_data.keys()),
  1398. ['code', 'message', 'task_id', 'url']
  1399. )
  1400. self.assertEqual(js_data['code'], 'OK')
  1401. self.assertEqual(js_data['message'], 'Stats asked')
  1402. self.assertTrue(js_data['url'].startswith('/pv/task/'))
  1403. output = self.app.get(js_data['url'])
  1404. js_data2 = json.loads(output.get_data(as_text=True))
  1405. self.assertTrue(
  1406. js_data2 in [
  1407. {'results': "reference 'refs/heads/master' not found"},
  1408. {'results': "Reference 'refs/heads/master' not found"}
  1409. ]
  1410. )
  1411. def test_get_stats_commits_trend_git_populated(self):
  1412. ''' Test the get_stats_commits_trend from the internal API. '''
  1413. tests.create_projects(self.session)
  1414. tests.create_projects_git(
  1415. os.path.join(self.path, 'repos'), bare=True)
  1416. tests.add_content_git_repo(
  1417. os.path.join(self.path, 'repos', 'test.git'))
  1418. user = tests.FakeUser()
  1419. user.username = 'pingou'
  1420. with tests.user_set(self.app.application, user):
  1421. csrf_token = self.get_csrf()
  1422. # Content in git
  1423. data = {
  1424. 'repo': 'test',
  1425. 'csrf_token': csrf_token,
  1426. }
  1427. output = self.app.post('/pv/stats/commits/trend', data=data)
  1428. self.assertEqual(output.status_code, 200)
  1429. js_data = json.loads(output.get_data(as_text=True))
  1430. self.assertEqual(
  1431. sorted(js_data.keys()),
  1432. ['code', 'message', 'task_id', 'url']
  1433. )
  1434. self.assertEqual(js_data['code'], 'OK')
  1435. self.assertEqual(js_data['message'], 'Stats asked')
  1436. self.assertTrue(js_data['url'].startswith('/pv/task/'))
  1437. output = self.app.get(js_data['url'])
  1438. js_data2 = json.loads(output.get_data(as_text=True))
  1439. today = datetime.datetime.utcnow().date()
  1440. self.assertDictEqual(
  1441. js_data2,
  1442. {'results': [[str(today), 2]]}
  1443. )
  1444. def test_get_project_family_no_project(self):
  1445. ''' Test the get_project_family from the internal API. '''
  1446. output = self.app.post('/pv/test/family')
  1447. self.assertEqual(output.status_code, 404)
  1448. def test_get_project_family_no_csrf(self):
  1449. ''' Test the get_project_family from the internal API. '''
  1450. tests.create_projects(self.session)
  1451. tests.create_projects_git(
  1452. os.path.join(self.path, 'repos'), bare=True)
  1453. tests.add_content_git_repo(
  1454. os.path.join(self.path, 'repos', 'test.git'))
  1455. output = self.app.post('/pv/test/family')
  1456. self.assertEqual(output.status_code, 400)
  1457. js_data = json.loads(output.get_data(as_text=True))
  1458. self.assertEqual(
  1459. sorted(js_data.keys()),
  1460. ['code', 'message']
  1461. )
  1462. self.assertEqual(js_data['code'], 'ERROR')
  1463. self.assertEqual(js_data['message'], 'Invalid input submitted')
  1464. def test_get_project_family(self):
  1465. ''' Test the get_project_family from the internal API. '''
  1466. tests.create_projects(self.session)
  1467. tests.create_projects_git(
  1468. os.path.join(self.path, 'repos'), bare=True)
  1469. tests.add_content_git_repo(
  1470. os.path.join(self.path, 'repos', 'test.git'))
  1471. user = tests.FakeUser()
  1472. user.username = 'pingou'
  1473. with tests.user_set(self.app.application, user):
  1474. csrf_token = self.get_csrf()
  1475. data = {
  1476. 'csrf_token': csrf_token,
  1477. }
  1478. output = self.app.post('/pv/test/family', data=data)
  1479. self.assertEqual(output.status_code, 200)
  1480. js_data = json.loads(output.get_data(as_text=True))
  1481. self.assertEqual(
  1482. sorted(js_data.keys()),
  1483. ['code', 'family']
  1484. )
  1485. self.assertEqual(js_data['code'], 'OK')
  1486. self.assertEqual(js_data['family'], ['test'])
  1487. def test_get_project_larger_family(self):
  1488. ''' Test the get_project_family from the internal API. '''
  1489. tests.create_projects(self.session)
  1490. tests.create_projects_git(
  1491. os.path.join(self.path, 'repos'), bare=True)
  1492. # Create a 3rd user
  1493. item = pagure.lib.model.User(
  1494. user='ralph',
  1495. fullname='Ralph bar',
  1496. password='ralph_foo',
  1497. default_email='ralph@bar.com',
  1498. )
  1499. self.session.add(item)
  1500. item = pagure.lib.model.UserEmail(
  1501. user_id=3,
  1502. email='ralph@bar.com')
  1503. self.session.add(item)
  1504. self.session.commit()
  1505. # Create a couple of forks of the test project
  1506. item = pagure.lib.model.Project(
  1507. user_id=2, # foo
  1508. name='test',
  1509. is_fork=True,
  1510. parent_id=1, # test
  1511. description='test project #1',
  1512. hook_token='aaabbbcccddd',
  1513. )
  1514. item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
  1515. self.session.add(item)
  1516. item = pagure.lib.model.Project(
  1517. user_id=3, # Ralph
  1518. name='test',
  1519. is_fork=True,
  1520. parent_id=1, # test
  1521. description='test project #1',
  1522. hook_token='aaabbbccceee',
  1523. )
  1524. item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
  1525. self.session.add(item)
  1526. self.session.commit()
  1527. # Get on with testing
  1528. user = tests.FakeUser()
  1529. user.username = 'pingou'
  1530. with tests.user_set(self.app.application, user):
  1531. csrf_token = self.get_csrf()
  1532. data = {
  1533. 'csrf_token': csrf_token,
  1534. }
  1535. output = self.app.post('/pv/test/family', data=data)
  1536. self.assertEqual(output.status_code, 200)
  1537. js_data = json.loads(output.get_data(as_text=True))
  1538. self.assertEqual(
  1539. sorted(js_data.keys()),
  1540. ['code', 'family']
  1541. )
  1542. self.assertEqual(js_data['code'], 'OK')
  1543. self.assertEqual(
  1544. js_data['family'],
  1545. ['test', 'fork/foo/test', 'fork/ralph/test'])
  1546. def test_get_pull_request_ready_branch_main_repo_no_branch(self):
  1547. '''Test the get_pull_request_ready_branch from the internal API
  1548. on the main repository
  1549. '''
  1550. tests.create_projects(self.session)
  1551. tests.create_projects_git(
  1552. os.path.join(self.path, 'repos'), bare=True)
  1553. # Get on with testing
  1554. user = tests.FakeUser()
  1555. user.username = 'pingou'
  1556. with tests.user_set(self.app.application, user):
  1557. csrf_token = self.get_csrf()
  1558. # Query branches on the main repo
  1559. data = {
  1560. 'csrf_token': csrf_token,
  1561. 'repo': 'test',
  1562. }
  1563. output = self.app.post('/pv/pull-request/ready', data=data)
  1564. self.assertEqual(output.status_code, 200)
  1565. js_data = json.loads(output.get_data(as_text=True))
  1566. self.assertEqual(
  1567. sorted(js_data.keys()),
  1568. ['code', 'message']
  1569. )
  1570. self.assertEqual(js_data['code'], 'OK')
  1571. self.assertEqual(
  1572. js_data['message'],
  1573. {'branch_w_pr': {}, 'new_branch': {}})
  1574. def test_get_pull_request_ready_branch_on_fork(self):
  1575. '''Test the get_pull_request_ready_branch from the internal API on
  1576. a fork
  1577. '''
  1578. tests.create_projects(self.session)
  1579. tests.create_projects_git(
  1580. os.path.join(self.path, 'repos'), bare=True)
  1581. tests.create_projects_git(
  1582. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  1583. tests.add_content_git_repo(
  1584. os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git'),
  1585. branch='feature')
  1586. # Create foo's fork of the test project
  1587. item = pagure.lib.model.Project(
  1588. user_id=2, # foo
  1589. name='test',
  1590. is_fork=True,
  1591. parent_id=1, # test
  1592. description='test project #1',
  1593. hook_token='aaabbbcccddd',
  1594. )
  1595. item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
  1596. self.session.add(item)
  1597. self.session.commit()
  1598. # Get on with testing
  1599. user = tests.FakeUser()
  1600. user.username = 'pingou'
  1601. with tests.user_set(self.app.application, user):
  1602. csrf_token = self.get_csrf()
  1603. # Query branches on the Ralph's fork
  1604. data = {
  1605. 'csrf_token': csrf_token,
  1606. 'repo': 'test',
  1607. 'repouser': 'foo',
  1608. }
  1609. output = self.app.post('/pv/pull-request/ready', data=data)
  1610. self.assertEqual(output.status_code, 200)
  1611. js_data = json.loads(output.get_data(as_text=True))
  1612. self.assertEqual(
  1613. sorted(js_data.keys()),
  1614. ['code', 'message']
  1615. )
  1616. self.assertEqual(js_data['code'], 'OK')
  1617. self.assertListEqual(
  1618. sorted(js_data['message'].keys()),
  1619. ['branch_w_pr', 'new_branch'])
  1620. self.assertEqual(js_data['message']['branch_w_pr'], {})
  1621. self.assertListEqual(
  1622. list(js_data['message']['new_branch']), ['feature'])
  1623. self.assertEqual(len(js_data['message']['new_branch']['feature']), 2)
  1624. def test_get_pull_request_ready_branch_on_fork_no_parent_no_pr(self):
  1625. '''Test the get_pull_request_ready_branch from the internal API on
  1626. a fork that has no parent repo (deleted) and doesn't allow PR
  1627. '''
  1628. tests.create_projects(self.session)
  1629. tests.create_projects_git(
  1630. os.path.join(self.path, 'repos'), bare=True)
  1631. tests.create_projects_git(
  1632. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  1633. tests.add_content_git_repo(
  1634. os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git'),
  1635. branch='feature')
  1636. # Create foo's fork of the test project
  1637. item = pagure.lib.model.Project(
  1638. user_id=2, # foo
  1639. name='test',
  1640. is_fork=True,
  1641. parent_id=1, # test
  1642. description='test project #1',
  1643. hook_token='aaabbbcccddd',
  1644. )
  1645. item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
  1646. self.session.add(item)
  1647. self.session.commit()
  1648. settings = item.settings
  1649. settings['pull_requests'] = False
  1650. item.settings = settings
  1651. self.session.add(item)
  1652. self.session.commit()
  1653. # Delete the parent project
  1654. project = pagure.lib.get_authorized_project(self.session, 'test')
  1655. self.session.delete(project)
  1656. self.session.commit()
  1657. # Get on with testing
  1658. user = tests.FakeUser()
  1659. user.username = 'pingou'
  1660. with tests.user_set(self.app.application, user):
  1661. csrf_token = self.get_csrf()
  1662. # Query branches on the Ralph's fork
  1663. data = {
  1664. 'csrf_token': csrf_token,
  1665. 'repo': 'test',
  1666. 'repouser': 'foo',
  1667. }
  1668. output = self.app.post('/pv/pull-request/ready', data=data)
  1669. self.assertEqual(output.status_code, 400)
  1670. js_data = json.loads(output.get_data(as_text=True))
  1671. self.assertEqual(
  1672. sorted(js_data.keys()),
  1673. ['code', 'message']
  1674. )
  1675. self.assertEqual(js_data['code'], 'ERROR')
  1676. self.assertEqual(
  1677. js_data['message'],
  1678. 'Pull-request have been disabled for this repo')
  1679. def test_get_pull_request_ready_branch_on_fork_no_parent(self):
  1680. '''Test the get_pull_request_ready_branch from the internal API on
  1681. a fork that has no parent repo (deleted).
  1682. '''
  1683. tests.create_projects(self.session)
  1684. tests.create_projects_git(
  1685. os.path.join(self.path, 'repos'), bare=True)
  1686. tests.create_projects_git(
  1687. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  1688. tests.add_content_git_repo(
  1689. os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git'),
  1690. branch='feature')
  1691. # Create foo's fork of the test project
  1692. item = pagure.lib.model.Project(
  1693. user_id=2, # foo
  1694. name='test',
  1695. is_fork=True,
  1696. parent_id=1, # test
  1697. description='test project #1',
  1698. hook_token='aaabbbcccddd',
  1699. )
  1700. item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
  1701. self.session.add(item)
  1702. self.session.commit()
  1703. settings = item.settings
  1704. settings['pull_requests'] = True
  1705. item.settings = settings
  1706. self.session.add(item)
  1707. self.session.commit()
  1708. # Delete the parent project
  1709. project = pagure.lib.get_authorized_project(self.session, 'test')
  1710. self.session.delete(project)
  1711. self.session.commit()
  1712. # Get on with testing
  1713. user = tests.FakeUser()
  1714. user.username = 'pingou'
  1715. with tests.user_set(self.app.application, user):
  1716. csrf_token = self.get_csrf()
  1717. # Query branches on the Ralph's fork
  1718. data = {
  1719. 'csrf_token': csrf_token,
  1720. 'repo': 'test',
  1721. 'repouser': 'foo',
  1722. }
  1723. output = self.app.post('/pv/pull-request/ready', data=data)
  1724. self.assertEqual(output.status_code, 200)
  1725. js_data = json.loads(output.get_data(as_text=True))
  1726. self.assertEqual(
  1727. sorted(js_data.keys()),
  1728. ['code', 'message']
  1729. )
  1730. self.assertEqual(js_data['code'], 'OK')
  1731. self.assertEqual(
  1732. sorted(js_data['message'].keys()),
  1733. ['branch_w_pr', 'new_branch'])
  1734. self.assertEqual(js_data['message']['branch_w_pr'], {})
  1735. self.assertListEqual(
  1736. list(js_data['message']['new_branch']), ['feature'])
  1737. self.assertEqual(len(js_data['message']['new_branch']['feature']), 2)
  1738. if __name__ == '__main__':
  1739. unittest.main(verbosity=2)