test_pagure_flask_ui_fork.py 108 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2017 - 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. from bs4 import BeautifulSoup
  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. def _get_commits(output):
  26. ''' Returns the commits message in the output. All commits must have
  27. been made by `Alice Author` or `PY C` to be found.
  28. '''
  29. commits = []
  30. save = False
  31. cnt = 0
  32. for row in output.split('\n'):
  33. if row.strip() in ['Alice Author', 'Alice Äuthòr', 'PY C']:
  34. save = True
  35. if save:
  36. cnt += 1
  37. if cnt == 7:
  38. commits.append(row.strip())
  39. save = False
  40. cnt = 0
  41. return commits
  42. class PagureFlaskForktests(tests.Modeltests):
  43. """ Tests for flask fork controller of pagure """
  44. def set_up_git_repo(
  45. self, new_project=None, branch_from='feature', mtype='FF',
  46. prid=1, name_from='test'):
  47. """ Set up the git repo and create the corresponding PullRequest
  48. object.
  49. """
  50. # Create a git repo to play with
  51. gitrepo = os.path.join(self.path, 'repos', '%s.git' % name_from)
  52. repo = pygit2.init_repository(gitrepo, bare=True)
  53. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  54. repopath = os.path.join(newpath, 'test')
  55. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  56. # Create a file in that git repo
  57. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  58. stream.write('foo\n bar')
  59. clone_repo.index.add('sources')
  60. clone_repo.index.write()
  61. try:
  62. com = repo.revparse_single('HEAD')
  63. prev_commit = [com.oid.hex]
  64. except:
  65. prev_commit = []
  66. # Commits the files added
  67. tree = clone_repo.index.write_tree()
  68. author = pygit2.Signature(
  69. 'Alice Author', 'alice@authors.tld')
  70. committer = pygit2.Signature(
  71. 'Cecil Committer', 'cecil@committers.tld')
  72. clone_repo.create_commit(
  73. 'refs/heads/master', # the name of the reference to update
  74. author,
  75. committer,
  76. 'Add sources file for testing',
  77. # binary string representing the tree object ID
  78. tree,
  79. # list of binary strings representing parents of the new commit
  80. prev_commit
  81. )
  82. time.sleep(1)
  83. refname = 'refs/heads/master:refs/heads/master'
  84. ori_remote = clone_repo.remotes[0]
  85. PagureRepo.push(ori_remote, refname)
  86. first_commit = repo.revparse_single('HEAD')
  87. if mtype == 'merge':
  88. with open(os.path.join(repopath, '.gitignore'), 'w') as stream:
  89. stream.write('*~')
  90. clone_repo.index.add('.gitignore')
  91. clone_repo.index.write()
  92. # Commits the files added
  93. tree = clone_repo.index.write_tree()
  94. author = pygit2.Signature(
  95. 'Alice Äuthòr', 'alice@äuthòrs.tld')
  96. committer = pygit2.Signature(
  97. 'Cecil Cõmmîttër', 'cecil@cõmmîttërs.tld')
  98. clone_repo.create_commit(
  99. 'refs/heads/master',
  100. author,
  101. committer,
  102. 'Add .gitignore file for testing',
  103. # binary string representing the tree object ID
  104. tree,
  105. # list of binary strings representing parents of the new commit
  106. [first_commit.oid.hex]
  107. )
  108. refname = 'refs/heads/master:refs/heads/master'
  109. ori_remote = clone_repo.remotes[0]
  110. PagureRepo.push(ori_remote, refname)
  111. if mtype == 'conflicts':
  112. with open(os.path.join(repopath, 'sources'), 'w') as stream:
  113. stream.write('foo\n bar\nbaz')
  114. clone_repo.index.add('sources')
  115. clone_repo.index.write()
  116. # Commits the files added
  117. tree = clone_repo.index.write_tree()
  118. author = pygit2.Signature(
  119. 'Alice Author', 'alice@authors.tld')
  120. committer = pygit2.Signature(
  121. 'Cecil Committer', 'cecil@committers.tld')
  122. clone_repo.create_commit(
  123. 'refs/heads/master',
  124. author,
  125. committer,
  126. 'Add sources conflicting',
  127. # binary string representing the tree object ID
  128. tree,
  129. # list of binary strings representing parents of the new commit
  130. [first_commit.oid.hex]
  131. )
  132. refname = 'refs/heads/master:refs/heads/master'
  133. ori_remote = clone_repo.remotes[0]
  134. PagureRepo.push(ori_remote, refname)
  135. # Set the second repo
  136. new_gitrepo = repopath
  137. if new_project:
  138. # Create a new git repo to play with
  139. new_gitrepo = os.path.join(newpath, new_project.fullname)
  140. if not os.path.exists(new_gitrepo):
  141. os.makedirs(new_gitrepo)
  142. new_repo = pygit2.clone_repository(gitrepo, new_gitrepo)
  143. repo = pygit2.Repository(new_gitrepo)
  144. if mtype != 'nochanges':
  145. # Edit the sources file again
  146. with open(os.path.join(new_gitrepo, 'sources'), 'w') as stream:
  147. stream.write('foo\n bar\nbaz\n boose')
  148. repo.index.add('sources')
  149. repo.index.write()
  150. # Commits the files added
  151. tree = repo.index.write_tree()
  152. author = pygit2.Signature(
  153. 'Alice Author', 'alice@authors.tld')
  154. committer = pygit2.Signature(
  155. 'Cecil Committer', 'cecil@committers.tld')
  156. repo.create_commit(
  157. 'refs/heads/%s' % branch_from,
  158. author,
  159. committer,
  160. 'A commit on branch %s' % branch_from,
  161. tree,
  162. [first_commit.oid.hex]
  163. )
  164. refname = 'refs/heads/%s' % (branch_from)
  165. ori_remote = repo.remotes[0]
  166. PagureRepo.push(ori_remote, refname)
  167. # Create a PR for these changes
  168. project = pagure.lib.get_authorized_project(self.session, 'test')
  169. req = pagure.lib.new_pull_request(
  170. session=self.session,
  171. repo_from=project,
  172. branch_from=branch_from,
  173. repo_to=project,
  174. branch_to='master',
  175. title='PR from the %s branch' % branch_from,
  176. user='pingou',
  177. requestfolder=None,
  178. )
  179. self.session.commit()
  180. self.assertEqual(req.id, prid)
  181. self.assertEqual(req.title, 'PR from the %s branch' % branch_from)
  182. shutil.rmtree(newpath)
  183. def test_request_pull_reference(self):
  184. """ Test if there is a reference created for a new PR. """
  185. tests.create_projects(self.session)
  186. tests.create_projects_git(
  187. os.path.join(self.path, 'requests'), bare=True)
  188. self.set_up_git_repo(new_project=None, branch_from='feature')
  189. project = pagure.lib.get_authorized_project(self.session, 'test')
  190. self.assertEqual(len(project.requests), 1)
  191. # View the pull-request
  192. output = self.app.get('/test/pull-request/1')
  193. self.assertEqual(output.status_code, 200)
  194. # Give time to the worker to process the task
  195. time.sleep(1)
  196. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  197. repo = pygit2.Repository(gitrepo)
  198. self.assertEqual(
  199. list(repo.listall_references()),
  200. ['refs/heads/feature', 'refs/heads/master', 'refs/pull/1/head']
  201. )
  202. @patch('pagure.lib.notify.send_email')
  203. def test_request_pull(self, send_email):
  204. """ Test the request_pull endpoint. """
  205. send_email.return_value = True
  206. tests.create_projects(self.session)
  207. tests.create_projects_git(
  208. os.path.join(self.path, 'requests'), bare=True)
  209. # Non-existant project
  210. output = self.app.get('/foobar/pull-request/1')
  211. self.assertEqual(output.status_code, 404)
  212. # Project has no PR
  213. output = self.app.get('/test/pull-request/1')
  214. self.assertEqual(output.status_code, 404)
  215. self.set_up_git_repo(new_project=None, branch_from='feature')
  216. project = pagure.lib.get_authorized_project(self.session, 'test')
  217. self.assertEqual(len(project.requests), 1)
  218. # View the pull-request
  219. output = self.app.get('/test/pull-request/1')
  220. self.assertEqual(output.status_code, 200)
  221. #self.assertIn(
  222. #'<h3><span class="label label-default">PR#1</span>\n'
  223. #' PR from the feature branch\n</h3>', output.data)
  224. self.assertIn(
  225. 'title="View file as of 2a552b">sources</a>', output.data)
  226. # Test if the `open changed file icon` is displayed.
  227. self.assertIn(
  228. 'class="open_changed_file_icon_wrap"><span '
  229. 'class="oi open_changed_file_icon" data-glyph="eye" '
  230. 'alt="Open changed file" title="Open changed file"></span>'
  231. '</a>', output.data)
  232. self.assertIn(
  233. '<span class="label label-success '
  234. 'pull-xs-right text-mono">+3</span>', output.data)
  235. self.assertIn(
  236. '<span class="label label-danger pull-xs-right">-1</span>',
  237. output.data)
  238. @patch('pagure.lib.notify.send_email')
  239. def test_merge_request_pull_FF(self, send_email):
  240. """ Test the merge_request_pull endpoint with a FF PR. """
  241. send_email.return_value = True
  242. self.test_request_pull()
  243. user = tests.FakeUser()
  244. with tests.user_set(self.app.application, user):
  245. output = self.app.get('/test/pull-request/1')
  246. self.assertEqual(output.status_code, 200)
  247. csrf_token = self.get_csrf(output=output)
  248. # No CSRF
  249. output = self.app.post(
  250. '/test/pull-request/1/merge', data={}, follow_redirects=True)
  251. self.assertEqual(output.status_code, 200)
  252. self.assertIn(
  253. '<title>PR#1: PR from the feature branch - test\n - '
  254. 'Pagure</title>', output.data)
  255. #self.assertIn(
  256. #'<h3><span class="label label-default">PR#1</span>\n'
  257. #' PR from the feature branch\n</h3>', output.data)
  258. self.assertIn(
  259. 'title="View file as of 2a552b">sources</a>', output.data)
  260. # Wrong project
  261. data = {
  262. 'csrf_token': csrf_token,
  263. }
  264. output = self.app.post(
  265. '/foobar/pull-request/100/merge', data=data, follow_redirects=True)
  266. self.assertEqual(output.status_code, 404)
  267. # Wrong project
  268. data = {
  269. 'csrf_token': csrf_token,
  270. }
  271. output = self.app.post(
  272. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  273. self.assertEqual(output.status_code, 403)
  274. user.username = 'pingou'
  275. with tests.user_set(self.app.application, user):
  276. # Wrong request id
  277. data = {
  278. 'csrf_token': csrf_token,
  279. }
  280. output = self.app.post(
  281. '/test/pull-request/100/merge', data=data, follow_redirects=True)
  282. self.assertEqual(output.status_code, 404)
  283. # Project w/o pull-request
  284. self.session.commit()
  285. repo = pagure.lib.get_authorized_project(self.session, 'test')
  286. settings = repo.settings
  287. settings['pull_requests'] = False
  288. repo.settings = settings
  289. self.session.add(repo)
  290. self.session.commit()
  291. # Pull-request disabled
  292. output = self.app.post(
  293. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  294. self.assertEqual(output.status_code, 404)
  295. # Project w pull-request but only assignee can merge
  296. self.session.commit()
  297. repo = pagure.lib.get_authorized_project(self.session, 'test')
  298. settings['pull_requests'] = True
  299. settings['Only_assignee_can_merge_pull-request'] = True
  300. repo.settings = settings
  301. self.session.add(repo)
  302. self.session.commit()
  303. output = self.app.post(
  304. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  305. self.assertEqual(output.status_code, 200)
  306. self.assertIn(
  307. '<title>PR#1: PR from the feature branch - test\n - '
  308. 'Pagure</title>', output.data)
  309. self.assertIn(
  310. '<h3><span class="label label-default">PR#1</span>\n'
  311. ' PR from the feature branch\n <span class="pull-xs-right">',
  312. output.data)
  313. self.assertIn(
  314. '</button>\n This request must be '
  315. 'assigned to be merged', output.data)
  316. # PR assigned but not to this user
  317. self.session.commit()
  318. repo = pagure.lib.get_authorized_project(self.session, 'test')
  319. req = repo.requests[0]
  320. req.assignee_id = 2
  321. self.session.add(req)
  322. self.session.commit()
  323. output = self.app.post(
  324. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  325. self.assertEqual(output.status_code, 200)
  326. self.assertIn(
  327. '<h3><span class="label label-default">PR#1</span>\n'
  328. ' PR from the feature branch\n <span class="pull-xs-right">',
  329. output.data)
  330. self.assertIn(
  331. '</button>\n Only the assignee can '
  332. 'merge this review', output.data)
  333. # Project w/ minimal PR score
  334. self.session.commit()
  335. repo = pagure.lib.get_authorized_project(self.session, 'test')
  336. settings['Only_assignee_can_merge_pull-request'] = False
  337. settings['Minimum_score_to_merge_pull-request'] = 2
  338. repo.settings = settings
  339. self.session.add(repo)
  340. self.session.commit()
  341. output = self.app.post(
  342. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  343. self.assertEqual(output.status_code, 200)
  344. self.assertIn(
  345. '<h3><span class="label label-default">PR#1</span>\n'
  346. ' PR from the feature branch\n <span class="pull-xs-right">',
  347. output.data)
  348. self.assertIn(
  349. '</button>\n This request does not '
  350. 'have the minimum review score necessary to be merged',
  351. output.data)
  352. # Merge
  353. self.session.commit()
  354. repo = pagure.lib.get_authorized_project(self.session, 'test')
  355. settings['Minimum_score_to_merge_pull-request'] = -1
  356. repo.settings = settings
  357. self.session.add(repo)
  358. self.session.commit()
  359. output = self.app.post(
  360. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  361. self.assertEqual(output.status_code, 200)
  362. self.assertIn(
  363. '<title>Overview - test - Pagure</title>', output.data)
  364. self.assertIn(
  365. 'A commit on branch feature', output.data)
  366. self.assertNotIn(
  367. 'Merge #1 `PR from the feature branch`', output.data)
  368. # Ensure we have the new commit
  369. commits = _get_commits(output.data)
  370. self.assertEqual(
  371. commits,
  372. [
  373. 'A commit on branch feature',
  374. 'Add sources file for testing'
  375. ]
  376. )
  377. # Check if the closing notification was added
  378. output = self.app.get('/test/pull-request/1')
  379. self.assertIn(
  380. '<small><p>Pull-Request has been merged by pingou</p></small>',
  381. output.data)
  382. @patch('pagure.lib.notify.send_email')
  383. def test_merge_request_pull_merge(self, send_email):
  384. """ Test the merge_request_pull endpoint with a merge PR. """
  385. send_email.return_value = True
  386. tests.create_projects(self.session)
  387. tests.create_projects_git(
  388. os.path.join(self.path, 'requests'), bare=True)
  389. self.set_up_git_repo(
  390. new_project=None, branch_from='feature', mtype='merge')
  391. user = tests.FakeUser()
  392. user.username = 'pingou'
  393. with tests.user_set(self.app.application, user):
  394. output = self.app.get('/test/pull-request/1')
  395. self.assertEqual(output.status_code, 200)
  396. csrf_token = self.get_csrf(output=output)
  397. data = {
  398. 'csrf_token': csrf_token,
  399. }
  400. # Merge
  401. output = self.app.post(
  402. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  403. self.assertEqual(output.status_code, 200)
  404. self.assertIn(
  405. '<title>Overview - test - Pagure</title>', output.data)
  406. # Check if the closing notification was added
  407. output = self.app.get('/test/pull-request/1')
  408. self.assertIn(
  409. '<small><p>Pull-Request has been merged by pingou</p></small>',
  410. output.data)
  411. @patch('pagure.lib.notify.send_email')
  412. def test_merge_request_pull_merge_with_delete_branch(self, send_email):
  413. """ Test the merge_request_pull endpoint with a merge PR and delete source branch. """
  414. send_email.return_value = True
  415. tests.create_projects(self.session)
  416. tests.create_projects_git(
  417. os.path.join(self.path, 'requests'), bare=True)
  418. self.set_up_git_repo(
  419. new_project=None, branch_from='feature-branch', mtype='merge')
  420. user = tests.FakeUser()
  421. user.username = 'pingou'
  422. with tests.user_set(self.app.application, user):
  423. output = self.app.get('/test/pull-request/1')
  424. self.assertEqual(output.status_code, 200)
  425. data = {
  426. 'csrf_token': self.get_csrf(output=output),
  427. 'delete_branch': True,
  428. }
  429. # Merge
  430. output = self.app.post(
  431. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  432. self.assertEqual(output.status_code, 200)
  433. self.assertIn(
  434. '<title>Overview - test - Pagure</title>', output.data)
  435. # Check the branch is not mentioned
  436. self.assertNotIn(
  437. '<a class="" href="/test/branch/feature-branch"', output.data)
  438. @patch('pagure.lib.notify.send_email')
  439. def test_merge_request_pull_conflicts(self, send_email):
  440. """ Test the merge_request_pull endpoint with a conflicting PR. """
  441. send_email.return_value = True
  442. tests.create_projects(self.session)
  443. tests.create_projects_git(
  444. os.path.join(self.path, 'requests'), bare=True)
  445. self.set_up_git_repo(
  446. new_project=None, branch_from='feature', mtype='conflicts')
  447. user = tests.FakeUser()
  448. user.username = 'pingou'
  449. with tests.user_set(self.app.application, user):
  450. output = self.app.get('/test/pull-request/1')
  451. self.assertEqual(output.status_code, 200)
  452. csrf_token = self.get_csrf(output=output)
  453. data = {
  454. 'csrf_token': csrf_token,
  455. }
  456. # Merge conflicts
  457. output = self.app.post(
  458. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  459. self.assertEqual(output.status_code, 200)
  460. self.assertIn(
  461. '<h3><span class="label label-default">PR#1</span>\n'
  462. ' PR from the feature branch\n <span class="pull-xs-right">',
  463. output.data)
  464. self.assertIn('Merge conflicts!', output.data)
  465. @patch('pagure.lib.notify.send_email')
  466. def test_merge_request_pull_conflicts_with_delete_branch(self, send_email):
  467. """ Test the merge_request_pull endpoint with a conflicting PR and request deletion of branch. """
  468. send_email.return_value = True
  469. tests.create_projects(self.session)
  470. tests.create_projects_git(
  471. os.path.join(self.path, 'requests'), bare=True)
  472. self.set_up_git_repo(
  473. new_project=None, branch_from='feature-branch', mtype='conflicts')
  474. user = tests.FakeUser()
  475. user.username = 'pingou'
  476. with tests.user_set(self.app.application, user):
  477. output = self.app.get('/test/pull-request/1')
  478. self.assertEqual(output.status_code, 200)
  479. data = {
  480. 'csrf_token': self.get_csrf(output=output),
  481. 'delete_branch': True,
  482. }
  483. # Merge conflicts
  484. output = self.app.post(
  485. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  486. self.assertEqual(output.status_code, 200)
  487. self.assertIn(
  488. '<h3><span class="label label-default">PR#1</span>\n'
  489. ' PR from the feature-branch branch\n <span class="pull-xs-right">',
  490. output.data)
  491. self.assertIn('Merge conflicts!', output.data)
  492. # Check the branch still exists
  493. output = self.app.get('/test')
  494. self.assertIn('feature-branch', output.data)
  495. @patch('pagure.lib.notify.send_email')
  496. def test_merge_request_pull_nochange(self, send_email):
  497. """ Test the merge_request_pull endpoint. """
  498. send_email.return_value = True
  499. tests.create_projects(self.session)
  500. tests.create_projects_git(
  501. os.path.join(self.path, 'requests'), bare=True)
  502. self.set_up_git_repo(
  503. new_project=None, branch_from='master', mtype='nochanges')
  504. user = tests.FakeUser()
  505. user.username = 'pingou'
  506. with tests.user_set(self.app.application, user):
  507. output = self.app.get('/test/pull-request/1')
  508. self.assertEqual(output.status_code, 200)
  509. csrf_token = self.get_csrf(output=output)
  510. data = {
  511. 'csrf_token': csrf_token,
  512. }
  513. # Nothing to merge
  514. output = self.app.post(
  515. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  516. self.assertEqual(output.status_code, 200)
  517. self.assertIn(
  518. '<h3><span class="label label-default">PR#1</span>\n'
  519. ' <span class="label label-success">Merged</span>',
  520. output.data)
  521. self.assertIn('Nothing to do, changes were already merged',
  522. output.data)
  523. # Check if the closing notification was added
  524. output = self.app.get('/test/pull-request/1')
  525. self.assertIn(
  526. '<small><p>Pull-Request has been merged by pingou</p></small>',
  527. output.data)
  528. @patch('pagure.lib.notify.send_email')
  529. def test_request_pull_close(self, send_email):
  530. """ Test the request_pull endpoint with a closed PR. """
  531. send_email.return_value = True
  532. self.test_merge_request_pull_FF()
  533. output = self.app.get('/test/pull-request/1')
  534. self.assertEqual(output.status_code, 200)
  535. self.assertIn(
  536. '<h3><span class="label label-default">PR#1</span>\n'
  537. ' <span class="label label-success">', output.data)
  538. self.assertIn('<div>Merged by\n', output.data)
  539. self.assertIn(
  540. 'title="View file as of 2a552b">sources</a>', output.data)
  541. @patch('pagure.lib.notify.send_email')
  542. def test_request_pull_disabled(self, send_email):
  543. """ Test the request_pull endpoint with PR disabled. """
  544. send_email.return_value = True
  545. tests.create_projects(self.session)
  546. tests.create_projects_git(
  547. os.path.join(self.path, 'requests'), bare=True)
  548. self.set_up_git_repo(new_project=None, branch_from='feature')
  549. # Project w/o pull-request
  550. repo = pagure.lib.get_authorized_project(self.session, 'test')
  551. settings = repo.settings
  552. settings['pull_requests'] = False
  553. repo.settings = settings
  554. self.session.add(repo)
  555. self.session.commit()
  556. output = self.app.get('/test/pull-request/1')
  557. self.assertEqual(output.status_code, 404)
  558. @patch('pagure.lib.notify.send_email')
  559. @patch('pagure.lib.git.update_pull_ref')
  560. def test_request_pull_empty_repo(self, send_email, update_pull_ref):
  561. """ Test the request_pull endpoint against an empty repo. """
  562. # Mock update_pull_ref or the repo won't be empty anymore
  563. # (the PR will have been pushed to refs/pull)
  564. send_email.return_value = True
  565. tests.create_projects(self.session)
  566. item = pagure.lib.model.Project(
  567. user_id=2, # foo
  568. name='test',
  569. description='test project #1',
  570. hook_token='aaabbb',
  571. is_fork=True,
  572. parent_id=1,
  573. )
  574. self.session.add(item)
  575. self.session.commit()
  576. tests.create_projects_git(
  577. os.path.join(self.path, 'requests'), bare=True)
  578. tests.create_projects_git(
  579. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  580. # Create a git repo to play with
  581. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  582. self.assertFalse(os.path.exists(gitrepo))
  583. os.makedirs(gitrepo)
  584. repo = pygit2.init_repository(gitrepo, bare=True)
  585. # Create a fork of this repo
  586. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  587. gitrepo = os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git')
  588. new_repo = pygit2.clone_repository(gitrepo, newpath)
  589. # Edit the sources file again
  590. with open(os.path.join(newpath, 'sources'), 'w') as stream:
  591. stream.write('foo\n bar\nbaz\n boose')
  592. new_repo.index.add('sources')
  593. new_repo.index.write()
  594. # Commits the files added
  595. tree = new_repo.index.write_tree()
  596. author = pygit2.Signature(
  597. 'Alice Author', 'alice@authors.tld')
  598. committer = pygit2.Signature(
  599. 'Cecil Committer', 'cecil@committers.tld')
  600. new_repo.create_commit(
  601. 'refs/heads/feature',
  602. author,
  603. committer,
  604. 'A commit on branch feature',
  605. tree,
  606. []
  607. )
  608. refname = 'refs/heads/feature:refs/heads/feature'
  609. ori_remote = new_repo.remotes[0]
  610. PagureRepo.push(ori_remote, refname)
  611. # Create a PR for these changes
  612. project = pagure.lib.get_authorized_project(self.session, 'test')
  613. req = pagure.lib.new_pull_request(
  614. session=self.session,
  615. repo_from=item,
  616. branch_from='feature',
  617. repo_to=project,
  618. branch_to='master',
  619. title='PR from the feature branch',
  620. user='pingou',
  621. requestfolder=None,
  622. )
  623. self.session.commit()
  624. self.assertEqual(req.id, 1)
  625. self.assertEqual(req.title, 'PR from the feature branch')
  626. output = self.app.get('/test/pull-request/1')
  627. self.assertEqual(output.status_code, 200)
  628. self.assertIn(
  629. '<h3><span class="label label-default">PR#1</span>\n'
  630. ' PR from the feature branch\n</h3>', output.data)
  631. self.assertTrue(
  632. output.data.count('<span class="commitdate" title='), 1)
  633. self.assertTrue(update_pull_ref.called)
  634. shutil.rmtree(newpath)
  635. @patch('pagure.lib.notify.send_email')
  636. def test_request_pull_empty_fork(self, send_email):
  637. """ Test the request_pull endpoint from an empty fork. """
  638. send_email.return_value = True
  639. tests.create_projects(self.session)
  640. item = pagure.lib.model.Project(
  641. user_id=2, # foo
  642. name='test',
  643. description='test project #1',
  644. hook_token='aaabbb',
  645. is_fork=True,
  646. parent_id=1,
  647. )
  648. self.session.add(item)
  649. self.session.commit()
  650. tests.create_projects_git(
  651. os.path.join(self.path, 'requests'), bare=True)
  652. tests.create_projects_git(
  653. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  654. # Create a git repo to play with
  655. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  656. self.assertFalse(os.path.exists(gitrepo))
  657. os.makedirs(gitrepo)
  658. repo = pygit2.init_repository(gitrepo, bare=True)
  659. # Create a fork of this repo
  660. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  661. gitrepo = os.path.join(
  662. self.path, 'repos', 'forks', 'foo', 'test.git')
  663. new_repo = pygit2.clone_repository(gitrepo, newpath)
  664. # Create a PR for these "changes" (there are none, both repos are
  665. # empty)
  666. project = pagure.lib.get_authorized_project(self.session, 'test')
  667. req = pagure.lib.new_pull_request(
  668. session=self.session,
  669. repo_from=item,
  670. branch_from='feature',
  671. repo_to=project,
  672. branch_to='master',
  673. title='PR from the feature branch',
  674. user='pingou',
  675. requestfolder=None,
  676. )
  677. self.session.commit()
  678. self.assertEqual(req.id, 1)
  679. self.assertEqual(req.title, 'PR from the feature branch')
  680. output = self.app.get('/test/pull-request/1', follow_redirects=True)
  681. self.assertEqual(output.status_code, 200)
  682. self.assertIn(
  683. '<title>Overview - test - Pagure</title>', output.data)
  684. self.assertIn(
  685. u'</button>\n Fork is empty, there are no '
  686. u'commits to create a pull request with', output.data)
  687. shutil.rmtree(newpath)
  688. @patch('pagure.lib.notify.send_email')
  689. def test_request_pulls(self, send_email):
  690. """ Test the request_pulls endpoint. """
  691. send_email.return_value = True
  692. # No such project
  693. output = self.app.get('/test/pull-requests')
  694. self.assertEqual(output.status_code, 404)
  695. tests.create_projects(self.session)
  696. tests.create_projects_git(
  697. os.path.join(self.path, 'repos'), bare=True)
  698. output = self.app.get('/test/pull-requests')
  699. self.assertEqual(output.status_code, 200)
  700. self.assertIn(
  701. '<h2 class="p-b-1">\n 0 Pull Requests (of 0)\n </h2>',
  702. output.data)
  703. # Open is primary
  704. self.assertIn(
  705. '<a class="btn btn-primary btn-sm" '
  706. 'href="/test/pull-requests">Open</a>', output.data)
  707. self.assertIn(
  708. '<a class="btn btn-secondary btn-sm" '
  709. 'href="/test/pull-requests?status=0">Closed</a>', output.data)
  710. self.set_up_git_repo(new_project=None, branch_from='feature')
  711. output = self.app.get('/test/pull-requests')
  712. self.assertEqual(output.status_code, 200)
  713. self.assertIn(
  714. '<h2 class="p-b-1">\n 1 Pull Requests (of 1)\n </h2>',
  715. output.data)
  716. # Open is primary
  717. self.assertIn(
  718. '<a class="btn btn-primary btn-sm" '
  719. 'href="/test/pull-requests">Open</a>', output.data)
  720. self.assertIn(
  721. '<a class="btn btn-secondary btn-sm" '
  722. 'href="/test/pull-requests?status=0">Closed</a>', output.data)
  723. output = self.app.get('/test/pull-requests?status=Closed')
  724. self.assertEqual(output.status_code, 200)
  725. self.assertIn(
  726. '<h2 class="p-b-1">\n 0 Closed Pull Requests (of 0)\n </h2>',
  727. output.data)
  728. # Close is primary
  729. self.assertIn(
  730. '<a class="btn btn-secondary btn-sm" '
  731. 'href="/test/pull-requests">Open</a>', output.data)
  732. self.assertIn(
  733. '<a class="btn btn-primary btn-sm" '
  734. 'href="/test/pull-requests?status=0">Closed</a>', output.data)
  735. output = self.app.get('/test/pull-requests?status=0')
  736. self.assertEqual(output.status_code, 200)
  737. self.assertIn(
  738. '<h2 class="p-b-1">\n 0 Closed/Merged Pull Requests (of 0)\n </h2>',
  739. output.data)
  740. # Close is primary
  741. self.assertIn(
  742. '<a class="btn btn-secondary btn-sm" '
  743. 'href="/test/pull-requests">Open</a>', output.data)
  744. self.assertIn(
  745. '<a class="btn btn-primary btn-sm" '
  746. 'href="/test/pull-requests?status=0">Closed</a>', output.data)
  747. # Project w/o pull-request
  748. repo = pagure.lib.get_authorized_project(self.session, 'test')
  749. settings = repo.settings
  750. settings['pull_requests'] = False
  751. repo.settings = settings
  752. self.session.add(repo)
  753. self.session.commit()
  754. output = self.app.get('/test/pull-requests')
  755. self.assertEqual(output.status_code, 404)
  756. @patch('pagure.lib.notify.send_email')
  757. def test_request_pull_patch(self, send_email):
  758. """ Test the request_pull_patch endpoint. """
  759. send_email.return_value = True
  760. output = self.app.get('/test/pull-request/1.patch')
  761. self.assertEqual(output.status_code, 404)
  762. tests.create_projects(self.session)
  763. tests.create_projects_git(
  764. os.path.join(self.path, 'requests'), bare=True)
  765. self.set_up_git_repo(
  766. new_project=None, branch_from='feature', mtype='merge')
  767. output = self.app.get('/test/pull-request/100.patch')
  768. self.assertEqual(output.status_code, 404)
  769. output = self.app.get('/test/pull-request/1.patch')
  770. self.assertEqual(output.status_code, 200)
  771. npatch = []
  772. for row in output.data.split('\n'):
  773. if row.startswith('Date:'):
  774. continue
  775. if row.startswith('From '):
  776. row = row.split(' ', 2)[2]
  777. npatch.append(row)
  778. exp = """Mon Sep 17 00:00:00 2001
  779. From: Alice Author <alice@authors.tld>
  780. Subject: A commit on branch feature
  781. ---
  782. diff --git a/.gitignore b/.gitignore
  783. new file mode 100644
  784. index 0000000..e4e5f6c
  785. --- /dev/null
  786. +++ b/.gitignore
  787. @@ -0,0 +1 @@
  788. +*~
  789. \ No newline at end of file
  790. diff --git a/sources b/sources
  791. index 9f44358..2a552bb 100644
  792. --- a/sources
  793. +++ b/sources
  794. @@ -1,2 +1,4 @@
  795. foo
  796. - bar
  797. \ No newline at end of file
  798. + bar
  799. +baz
  800. + boose
  801. \ No newline at end of file
  802. """
  803. patch = '\n'.join(npatch)
  804. #print patch
  805. self.assertEqual(patch, exp)
  806. # Project w/o pull-request
  807. repo = pagure.lib.get_authorized_project(self.session, 'test')
  808. settings = repo.settings
  809. settings['pull_requests'] = False
  810. repo.settings = settings
  811. self.session.add(repo)
  812. self.session.commit()
  813. output = self.app.get('/test/pull-request/1.patch')
  814. self.assertEqual(output.status_code, 404)
  815. @patch('pagure.lib.notify.send_email')
  816. def test_request_pull_diff(self, send_email):
  817. """ Test the request_pull_patch endpoint. """
  818. send_email.return_value = True
  819. output = self.app.get('/test/pull-request/1.diff')
  820. self.assertEqual(output.status_code, 404)
  821. tests.create_projects(self.session)
  822. tests.create_projects_git(
  823. os.path.join(self.path, 'requests'), bare=True)
  824. self.set_up_git_repo(
  825. new_project=None, branch_from='feature', mtype='merge')
  826. output = self.app.get('/test/pull-request/100.diff')
  827. self.assertEqual(output.status_code, 404)
  828. output = self.app.get('/test/pull-request/1.diff')
  829. self.assertEqual(output.status_code, 200)
  830. exp = """diff --git a/.gitignore b/.gitignore
  831. new file mode 100644
  832. index 0000000..e4e5f6c
  833. --- /dev/null
  834. +++ b/.gitignore
  835. @@ -0,0 +1 @@
  836. +*~
  837. \ No newline at end of file
  838. diff --git a/sources b/sources
  839. index 9f44358..2a552bb 100644
  840. --- a/sources
  841. +++ b/sources
  842. @@ -1,2 +1,4 @@
  843. foo
  844. - bar
  845. \ No newline at end of file
  846. + bar
  847. +baz
  848. + boose
  849. \ No newline at end of file
  850. """
  851. self.assertEqual(output.data, exp)
  852. # Project w/o pull-request
  853. repo = pagure.lib.get_authorized_project(self.session, 'test')
  854. settings = repo.settings
  855. settings['pull_requests'] = False
  856. repo.settings = settings
  857. self.session.add(repo)
  858. self.session.commit()
  859. output = self.app.get('/test/pull-request/1.diff')
  860. self.assertEqual(output.status_code, 404)
  861. @patch('pagure.lib.notify.send_email')
  862. def test_request_pull_patch_close(self, send_email):
  863. """ Test the request_pull_patch endpoint with a closed PR. """
  864. send_email.return_value = True
  865. self.test_merge_request_pull_FF()
  866. output = self.app.get('/test/pull-request/1.patch')
  867. self.assertEqual(output.status_code, 200)
  868. npatch = []
  869. for row in output.data.split('\n'):
  870. if row.startswith('Date:'):
  871. continue
  872. if row.startswith('From '):
  873. row = row.split(' ', 2)[2]
  874. npatch.append(row)
  875. exp = """Mon Sep 17 00:00:00 2001
  876. From: Alice Author <alice@authors.tld>
  877. Subject: A commit on branch feature
  878. ---
  879. diff --git a/sources b/sources
  880. index 9f44358..2a552bb 100644
  881. --- a/sources
  882. +++ b/sources
  883. @@ -1,2 +1,4 @@
  884. foo
  885. - bar
  886. \ No newline at end of file
  887. + bar
  888. +baz
  889. + boose
  890. \ No newline at end of file
  891. """
  892. patch = '\n'.join(npatch)
  893. #print patch
  894. self.assertEqual(patch, exp)
  895. @patch('pagure.lib.notify.send_email')
  896. @patch('pagure.lib.git.update_pull_ref')
  897. def test_request_pull_patch_empty_repo(self, send_email, update_pull_ref):
  898. """ Test the request_pull_patch endpoint against an empty repo. """
  899. # Mock update_pull_ref or the repo won't be empty anymore
  900. # (the PR will have been pushed to refs/pull)
  901. send_email.return_value = True
  902. tests.create_projects(self.session)
  903. item = pagure.lib.model.Project(
  904. user_id=2, # foo
  905. name='test',
  906. description='test project #1',
  907. hook_token='aaabbb',
  908. is_fork=True,
  909. parent_id=1,
  910. )
  911. self.session.add(item)
  912. self.session.commit()
  913. tests.create_projects_git(
  914. os.path.join(self.path, 'requests'), bare=True)
  915. tests.create_projects_git(
  916. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  917. # Create a git repo to play with
  918. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  919. self.assertFalse(os.path.exists(gitrepo))
  920. os.makedirs(gitrepo)
  921. repo = pygit2.init_repository(gitrepo, bare=True)
  922. # Create a fork of this repo
  923. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  924. gitrepo = os.path.join(
  925. self.path, 'repos', 'forks', 'foo', 'test.git')
  926. new_repo = pygit2.clone_repository(gitrepo, newpath)
  927. # Edit the sources file again
  928. with open(os.path.join(newpath, 'sources'), 'w') as stream:
  929. stream.write('foo\n bar\nbaz\n boose')
  930. new_repo.index.add('sources')
  931. new_repo.index.write()
  932. # Commits the files added
  933. tree = new_repo.index.write_tree()
  934. author = pygit2.Signature(
  935. 'Alice Author', 'alice@authors.tld')
  936. committer = pygit2.Signature(
  937. 'Cecil Committer', 'cecil@committers.tld')
  938. new_repo.create_commit(
  939. 'refs/heads/feature',
  940. author,
  941. committer,
  942. 'A commit on branch feature',
  943. tree,
  944. []
  945. )
  946. refname = 'refs/heads/feature:refs/heads/feature'
  947. ori_remote = new_repo.remotes[0]
  948. PagureRepo.push(ori_remote, refname)
  949. # Create a PR for these "changes" (there are none, both repos are
  950. # empty)
  951. project = pagure.lib.get_authorized_project(self.session, 'test')
  952. req = pagure.lib.new_pull_request(
  953. session=self.session,
  954. repo_from=item,
  955. branch_from='feature',
  956. repo_to=project,
  957. branch_to='master',
  958. title='PR from the feature branch',
  959. user='pingou',
  960. requestfolder=None,
  961. )
  962. self.session.commit()
  963. self.assertEqual(req.id, 1)
  964. self.assertEqual(req.title, 'PR from the feature branch')
  965. output = self.app.get(
  966. '/test/pull-request/1.patch', follow_redirects=True)
  967. self.assertEqual(output.status_code, 200)
  968. npatch = []
  969. for row in output.data.split('\n'):
  970. if row.startswith('Date:'):
  971. continue
  972. if row.startswith('From '):
  973. row = row.split(' ', 2)[2]
  974. npatch.append(row)
  975. exp = """Mon Sep 17 00:00:00 2001
  976. From: Alice Author <alice@authors.tld>
  977. Subject: A commit on branch feature
  978. ---
  979. diff --git a/sources b/sources
  980. new file mode 100644
  981. index 0000000..2a552bb
  982. --- /dev/null
  983. +++ b/sources
  984. @@ -0,0 +1,4 @@
  985. +foo
  986. + bar
  987. +baz
  988. + boose
  989. \ No newline at end of file
  990. """
  991. patch = '\n'.join(npatch)
  992. #print patch
  993. self.assertEqual(patch, exp)
  994. shutil.rmtree(newpath)
  995. @patch('pagure.lib.notify.send_email')
  996. def test_request_pull_patch_empty_fork(self, send_email):
  997. """ Test the request_pull_patch endpoint from an empty fork. """
  998. send_email.return_value = True
  999. tests.create_projects(self.session)
  1000. item = pagure.lib.model.Project(
  1001. user_id=2, # foo
  1002. name='test',
  1003. description='test project #1',
  1004. hook_token='aaabbb',
  1005. is_fork=True,
  1006. parent_id=1,
  1007. )
  1008. self.session.add(item)
  1009. self.session.commit()
  1010. tests.create_projects_git(
  1011. os.path.join(self.path, 'requests'), bare=True)
  1012. tests.create_projects_git(
  1013. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  1014. # Create a git repo to play with
  1015. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1016. self.assertFalse(os.path.exists(gitrepo))
  1017. os.makedirs(gitrepo)
  1018. repo = pygit2.init_repository(gitrepo, bare=True)
  1019. # Create a fork of this repo
  1020. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  1021. gitrepo = os.path.join(
  1022. self.path, 'repos', 'forks', 'foo', 'test.git')
  1023. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1024. # Create a PR for these "changes" (there are none, both repos are
  1025. # empty)
  1026. project = pagure.lib.get_authorized_project(self.session, 'test')
  1027. req = pagure.lib.new_pull_request(
  1028. session=self.session,
  1029. repo_from=item,
  1030. branch_from='feature',
  1031. repo_to=project,
  1032. branch_to='master',
  1033. title='PR from the feature branch',
  1034. user='pingou',
  1035. requestfolder=None,
  1036. )
  1037. self.session.commit()
  1038. self.assertEqual(req.id, 1)
  1039. self.assertEqual(req.title, 'PR from the feature branch')
  1040. output = self.app.get('/test/pull-request/1.patch', follow_redirects=True)
  1041. self.assertEqual(output.status_code, 200)
  1042. self.assertIn(
  1043. '<title>Overview - test - Pagure</title>', output.data)
  1044. self.assertIn(
  1045. u'</button>\n Fork is empty, there are no '
  1046. u'commits to create a pull request with', output.data)
  1047. shutil.rmtree(newpath)
  1048. @patch('pagure.lib.notify.send_email')
  1049. def test_cancel_request_pull(self, send_email):
  1050. """ Test the cancel_request_pull endpoint. """
  1051. send_email.return_value = True
  1052. tests.create_projects(self.session)
  1053. tests.create_projects_git(
  1054. os.path.join(self.path, 'requests'), bare=True)
  1055. self.set_up_git_repo(
  1056. new_project=None, branch_from='feature', mtype='merge')
  1057. user = tests.FakeUser()
  1058. with tests.user_set(self.app.application, user):
  1059. output = self.app.post('/test/pull-request/cancel/1')
  1060. self.assertEqual(output.status_code, 302)
  1061. output = self.app.post(
  1062. '/test/pull-request/cancel/1', follow_redirects=True)
  1063. self.assertEqual(output.status_code, 200)
  1064. self.assertIn(
  1065. '<title>Overview - test - Pagure</title>', output.data)
  1066. self.assertIn(
  1067. '</button>\n Invalid input submitted',
  1068. output.data)
  1069. output = self.app.get('/test/pull-request/1')
  1070. self.assertEqual(output.status_code, 200)
  1071. csrf_token = self.get_csrf(output=output)
  1072. data = {
  1073. 'csrf_token': csrf_token,
  1074. }
  1075. # Invalid project
  1076. output = self.app.post(
  1077. '/foo/pull-request/cancel/1', data=data,
  1078. follow_redirects=True)
  1079. self.assertEqual(output.status_code, 404)
  1080. # Invalid PR id
  1081. output = self.app.post(
  1082. '/test/pull-request/cancel/100', data=data,
  1083. follow_redirects=True)
  1084. self.assertEqual(output.status_code, 404)
  1085. # Invalid user for this project
  1086. output = self.app.post(
  1087. '/test/pull-request/cancel/1', data=data,
  1088. follow_redirects=True)
  1089. self.assertEqual(output.status_code, 403)
  1090. user.username = 'pingou'
  1091. with tests.user_set(self.app.application, user):
  1092. # Project w/o pull-request
  1093. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1094. settings = repo.settings
  1095. settings['pull_requests'] = False
  1096. repo.settings = settings
  1097. self.session.add(repo)
  1098. self.session.commit()
  1099. output = self.app.post(
  1100. '/test/pull-request/cancel/1', data=data,
  1101. follow_redirects=True)
  1102. self.assertEqual(output.status_code, 404)
  1103. # Project w/ pull-request
  1104. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1105. settings = repo.settings
  1106. settings['pull_requests'] = True
  1107. repo.settings = settings
  1108. self.session.add(repo)
  1109. self.session.commit()
  1110. output = self.app.post(
  1111. '/test/pull-request/cancel/1', data=data,
  1112. follow_redirects=True)
  1113. self.assertEqual(output.status_code, 200)
  1114. self.assertIn(
  1115. '<title>Overview - test - Pagure</title>', output.data)
  1116. self.assertIn(
  1117. '</button>\n Pull request canceled!',
  1118. output.data)
  1119. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  1120. def test_update_pull_requests_assign(self):
  1121. """ Test the update_pull_requests endpoint when assigning a PR.
  1122. """
  1123. tests.create_projects(self.session)
  1124. tests.create_projects_git(
  1125. os.path.join(self.path, 'requests'), bare=True)
  1126. self.set_up_git_repo(new_project=None, branch_from='feature')
  1127. user = tests.FakeUser()
  1128. user.username = 'pingou'
  1129. with tests.user_set(self.app.application, user):
  1130. # No such project
  1131. output = self.app.post('/foo/pull-request/1/update')
  1132. self.assertEqual(output.status_code, 404)
  1133. output = self.app.post('/test/pull-request/100/update')
  1134. self.assertEqual(output.status_code, 404)
  1135. # Invalid input
  1136. output = self.app.post(
  1137. '/test/pull-request/1/update', follow_redirects=True)
  1138. self.assertEqual(output.status_code, 200)
  1139. self.assertIn(
  1140. '<title>PR#1: PR from the feature branch - test\n - '
  1141. 'Pagure</title>', output.data)
  1142. self.assertIn(
  1143. '<h3><span class="label label-default">PR#1</span>\n'
  1144. ' PR from the feature branch\n', output.data)
  1145. self.assertNotIn(
  1146. '</button>\n Request assigned',
  1147. output.data)
  1148. output = self.app.get('/test/pull-request/1')
  1149. self.assertEqual(output.status_code, 200)
  1150. csrf_token = self.get_csrf(output=output)
  1151. data = {
  1152. 'user': 'pingou',
  1153. }
  1154. # No CSRF
  1155. output = self.app.post(
  1156. '/test/pull-request/1/update', data=data,
  1157. follow_redirects=True)
  1158. self.assertEqual(output.status_code, 200)
  1159. self.assertIn(
  1160. '<title>PR#1: PR from the feature branch - test\n - '
  1161. 'Pagure</title>', output.data)
  1162. self.assertIn(
  1163. '<h3><span class="label label-default">PR#1</span>\n'
  1164. ' PR from the feature branch\n', output.data)
  1165. self.assertNotIn(
  1166. '</button>\n Request assigned',
  1167. output.data)
  1168. # Invalid assignee
  1169. data = {
  1170. 'csrf_token': csrf_token,
  1171. 'user': 'bar',
  1172. }
  1173. output = self.app.post(
  1174. '/test/pull-request/1/update', data=data,
  1175. follow_redirects=True)
  1176. self.assertEqual(output.status_code, 200)
  1177. self.assertIn(
  1178. '<title>PR#1: PR from the feature branch - test\n - '
  1179. 'Pagure</title>', output.data)
  1180. self.assertIn(
  1181. '<h3><span class="label label-default">PR#1</span>\n'
  1182. ' PR from the feature branch\n', output.data)
  1183. self.assertIn(
  1184. '</button>\n No user &#34;bar&#34; found',
  1185. output.data)
  1186. # Assign the PR
  1187. data = {
  1188. 'csrf_token': csrf_token,
  1189. 'user': 'pingou',
  1190. }
  1191. user.username = 'foo'
  1192. with tests.user_set(self.app.application, user):
  1193. output = self.app.post(
  1194. '/test/pull-request/1/update', data=data,
  1195. follow_redirects=True)
  1196. self.assertEqual(output.status_code, 403)
  1197. user.username = 'pingou'
  1198. with tests.user_set(self.app.application, user):
  1199. output = self.app.post(
  1200. '/test/pull-request/1/update', data=data,
  1201. follow_redirects=True)
  1202. self.assertEqual(output.status_code, 200)
  1203. self.assertIn(
  1204. '<title>PR#1: PR from the feature branch - test\n - '
  1205. 'Pagure</title>', output.data)
  1206. self.assertIn(
  1207. '<h3><span class="label label-default">PR#1</span>\n'
  1208. ' PR from the feature branch\n', output.data)
  1209. self.assertIn(
  1210. '</button>\n Request assigned',
  1211. output.data)
  1212. # Pull-Request closed
  1213. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1214. req = repo.requests[0]
  1215. req.status = 'Closed'
  1216. req.closed_by_in = 1
  1217. self.session.add(req)
  1218. self.session.commit()
  1219. output = self.app.post(
  1220. '/test/pull-request/1/update', data=data,
  1221. follow_redirects=True)
  1222. self.assertEqual(output.status_code, 403)
  1223. # Project w/o pull-request
  1224. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1225. settings = repo.settings
  1226. settings['pull_requests'] = False
  1227. repo.settings = settings
  1228. self.session.add(repo)
  1229. self.session.commit()
  1230. output = self.app.post(
  1231. '/test/pull-request/1/update', data=data,
  1232. follow_redirects=True)
  1233. self.assertEqual(output.status_code, 404)
  1234. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  1235. def test_update_pull_requests_tag(self):
  1236. """ Test the update_pull_requests endpoint when tagging a PR.
  1237. """
  1238. tests.create_projects(self.session)
  1239. tests.create_projects_git(
  1240. os.path.join(self.path, 'requests'), bare=True)
  1241. self.set_up_git_repo(new_project=None, branch_from='feature')
  1242. user = tests.FakeUser()
  1243. user.username = 'pingou'
  1244. with tests.user_set(self.app.application, user):
  1245. output = self.app.get('/test/pull-request/1')
  1246. self.assertEqual(output.status_code, 200)
  1247. csrf_token = self.get_csrf(output=output)
  1248. data = {
  1249. 'tag': 'black',
  1250. }
  1251. # No CSRF
  1252. output = self.app.post(
  1253. '/test/pull-request/1/update', data=data,
  1254. follow_redirects=True)
  1255. self.assertEqual(output.status_code, 200)
  1256. self.assertIn(
  1257. '<title>PR#1: PR from the feature branch - test\n - '
  1258. 'Pagure</title>', output.data)
  1259. self.assertIn(
  1260. '<h3><span class="label label-default">PR#1</span>\n'
  1261. ' PR from the feature branch\n', output.data)
  1262. self.assertNotIn(
  1263. '</button>\n Request assigned',
  1264. output.data)
  1265. # Tag the PR
  1266. data = {
  1267. 'csrf_token': csrf_token,
  1268. 'tag': 'black',
  1269. }
  1270. output = self.app.post(
  1271. '/test/pull-request/1/update', data=data,
  1272. follow_redirects=True)
  1273. self.assertEqual(output.status_code, 200)
  1274. self.assertIn(
  1275. '<title>PR#1: PR from the feature branch - test\n - '
  1276. 'Pagure</title>', output.data)
  1277. self.assertIn(
  1278. '<h3><span class="label label-default">PR#1</span>\n'
  1279. ' PR from the feature branch\n', output.data)
  1280. self.assertIn(
  1281. '</button>\n Pull-request tagged with: black',
  1282. output.data)
  1283. self.assertIn(
  1284. 'title="comma separated list of tags"\n '
  1285. 'value="black" />', output.data)
  1286. # Try as another user
  1287. user.username = 'foo'
  1288. with tests.user_set(self.app.application, user):
  1289. # Tag the PR
  1290. data = {
  1291. 'csrf_token': csrf_token,
  1292. 'tag': 'blue, yellow',
  1293. }
  1294. output = self.app.post(
  1295. '/test/pull-request/1/update', data=data,
  1296. follow_redirects=True)
  1297. self.assertEqual(output.status_code, 403)
  1298. # Make the PR be from foo
  1299. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1300. req = repo.requests[0]
  1301. req.user_id = 2
  1302. self.session.add(req)
  1303. self.session.commit()
  1304. # Re-try to tag the PR
  1305. data = {
  1306. 'csrf_token': csrf_token,
  1307. 'tag': 'blue, yellow',
  1308. }
  1309. output = self.app.post(
  1310. '/test/pull-request/1/update', data=data,
  1311. follow_redirects=True)
  1312. self.assertEqual(output.status_code, 200)
  1313. soup = BeautifulSoup(output.data, "html.parser")
  1314. self.assertEqual(
  1315. soup.find("title").string,
  1316. 'PR#1: PR from the feature branch - test\n - Pagure'
  1317. )
  1318. h3 = soup.find("h3")
  1319. self.assertIsNotNone(h3)
  1320. self.assertListEqual(
  1321. h3.find("span")["class"], ["label", "label-default"])
  1322. self.assertEqual(h3.find("span").string, "PR#1")
  1323. self.assertEqual(
  1324. list(h3.stripped_strings)[1], 'PR from the feature branch')
  1325. alerts = [
  1326. list(a.stripped_strings)[2] for a in
  1327. soup.find_all("div", class_="alert")
  1328. if list(a.stripped_strings)
  1329. ]
  1330. self.assertIn('Pull-request **un**tagged with: black', alerts)
  1331. self.assertIn('Pull-request tagged with: blue, yellow', alerts)
  1332. input_tag = soup.find("input", id="tag")
  1333. self.assertEqual(
  1334. input_tag["title"], "comma separated list of tags")
  1335. # The order is not guaranteed, compare sets.
  1336. self.assertEqual(
  1337. set(input_tag["value"].split(",")),
  1338. set(["blue", "yellow"])
  1339. )
  1340. user.username = 'pingou'
  1341. with tests.user_set(self.app.application, user):
  1342. # Pull-Request closed
  1343. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1344. req = repo.requests[0]
  1345. req.status = 'Closed'
  1346. req.closed_by_in = 1
  1347. self.session.add(req)
  1348. self.session.commit()
  1349. output = self.app.post(
  1350. '/test/pull-request/1/update', data=data,
  1351. follow_redirects=True)
  1352. self.assertEqual(output.status_code, 403)
  1353. # Project w/o pull-request
  1354. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1355. settings = repo.settings
  1356. settings['pull_requests'] = False
  1357. repo.settings = settings
  1358. self.session.add(repo)
  1359. self.session.commit()
  1360. output = self.app.post(
  1361. '/test/pull-request/1/update', data=data,
  1362. follow_redirects=True)
  1363. self.assertEqual(output.status_code, 404)
  1364. @patch('pagure.lib.notify.send_email')
  1365. def test_fork_project(self, send_email):
  1366. """ Test the fork_project endpoint. """
  1367. send_email.return_value = True
  1368. tests.create_projects(self.session)
  1369. for folder in ['docs', 'tickets', 'requests', 'repos']:
  1370. tests.create_projects_git(
  1371. os.path.join(self.path, folder), bare=True)
  1372. user = tests.FakeUser()
  1373. user.username = 'pingou'
  1374. with tests.user_set(self.app.application, user):
  1375. output = self.app.post('/do_fork/test')
  1376. self.assertEqual(output.status_code, 400)
  1377. output = self.app.get('/new/')
  1378. self.assertEqual(output.status_code, 200)
  1379. self.assertIn('<strong>Create new Project</strong>', output.data)
  1380. csrf_token = self.get_csrf(output=output)
  1381. data = {
  1382. 'csrf_token': csrf_token,
  1383. }
  1384. output = self.app.post(
  1385. '/do_fork/foo', data=data, follow_redirects=True)
  1386. self.assertEqual(output.status_code, 404)
  1387. user.username = 'foo'
  1388. with tests.user_set(self.app.application, user):
  1389. output = self.app.post('/do_fork/test')
  1390. self.assertEqual(output.status_code, 400)
  1391. data = {
  1392. 'csrf_token': csrf_token,
  1393. }
  1394. output = self.app.post(
  1395. '/do_fork/test', data=data, follow_redirects=True)
  1396. self.assertEqual(output.status_code, 200)
  1397. @patch('pagure.lib.notify.send_email')
  1398. def test_new_request_pull(self, send_email):
  1399. """ Test the new_request_pull endpoint. """
  1400. send_email.return_value = True
  1401. self.test_fork_project()
  1402. tests.create_projects_git(
  1403. os.path.join(self.path, 'requests'), bare=True)
  1404. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1405. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1406. self.set_up_git_repo(
  1407. new_project=fork, branch_from='feature', mtype='FF')
  1408. user = tests.FakeUser()
  1409. user.username = 'foo'
  1410. with tests.user_set(self.app.application, user):
  1411. output = self.app.get('/foo/diff/master..feature')
  1412. self.assertEqual(output.status_code, 404)
  1413. output = self.app.get('/test/diff/master..foo')
  1414. self.assertEqual(output.status_code, 400)
  1415. output = self.app.get('/test/diff/foo..master')
  1416. self.assertEqual(output.status_code, 400)
  1417. output = self.app.get('/test/diff/feature..master')
  1418. self.assertEqual(output.status_code, 200)
  1419. self.assertIn(
  1420. '<title>Diff from master to feature - test\n - '
  1421. 'Pagure</title>', output.data)
  1422. self.assertIn(
  1423. '<p class="error"> No commits found </p>', output.data)
  1424. output = self.app.get('/test/diff/master..feature')
  1425. self.assertEqual(output.status_code, 200)
  1426. self.assertIn(
  1427. '<title>Diff from feature to master - test\n - '
  1428. 'Pagure</title>', output.data)
  1429. self.assertNotIn(
  1430. '<input type="submit" class="submit positive button" '
  1431. 'value="Create">', output.data)
  1432. user.username = 'pingou'
  1433. with tests.user_set(self.app.application, user):
  1434. output = self.app.get('/test/diff/master..feature')
  1435. self.assertEqual(output.status_code, 200)
  1436. self.assertIn(
  1437. '<title>Create new Pull Request for master - test\n - '
  1438. 'Pagure</title>', output.data)
  1439. self.assertIn(
  1440. '<input type="submit" class="btn btn-primary" value="Create">',
  1441. output.data)
  1442. csrf_token = self.get_csrf(output=output)
  1443. # Case 1 - Add an initial comment
  1444. data = {
  1445. 'csrf_token': csrf_token,
  1446. 'title': 'foo bar PR',
  1447. 'initial_comment': 'Test Initial Comment',
  1448. }
  1449. output = self.app.post(
  1450. '/test/diff/master..feature', data=data, follow_redirects=True)
  1451. self.assertEqual(output.status_code, 200)
  1452. self.assertIn(
  1453. '<title>PR#2: foo bar PR - test\n - Pagure</title>',
  1454. output.data)
  1455. self.assertIn('<p>Test Initial Comment</p>', output.data)
  1456. self.assertEqual(output.data.count('title="PY C (pingou)"'), 1)
  1457. # Test if the `open changed file icon` is displayed.
  1458. self.assertIn(
  1459. 'class="open_changed_file_icon_wrap"><span '
  1460. 'class="oi open_changed_file_icon" data-glyph="eye" '
  1461. 'alt="Open changed file" title="Open changed file"></span>'
  1462. '</a>', output.data)
  1463. # Case 2 - Add an empty initial comment
  1464. data = {
  1465. 'csrf_token': csrf_token,
  1466. 'title': 'foo bar PR',
  1467. 'initial_comment': '',
  1468. }
  1469. output = self.app.post(
  1470. '/test/diff/master..feature', data=data, follow_redirects=True)
  1471. self.assertEqual(output.status_code, 200)
  1472. self.assertIn(
  1473. '<title>PR#3: foo bar PR - test\n - Pagure</title>',
  1474. output.data)
  1475. self.assertNotIn('<div id="comment-', output.data)
  1476. @patch('pagure.lib.notify.send_email')
  1477. def test_new_request_pull_req_sign_off_view(self, send_email):
  1478. """ Test the new_request_pull endpoint. """
  1479. send_email.return_value = True
  1480. self.test_fork_project()
  1481. tests.create_projects_git(
  1482. os.path.join(self.path, 'requests'), bare=True)
  1483. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1484. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1485. # Enforce Signed-of-by in the repo
  1486. settings = repo.settings
  1487. settings['Enforce_signed-off_commits_in_pull-request'] = True
  1488. repo.settings = settings
  1489. self.session.add(repo)
  1490. self.session.commit()
  1491. self.set_up_git_repo(
  1492. new_project=fork, branch_from='feature', mtype='FF')
  1493. user = tests.FakeUser()
  1494. user.username = 'foo'
  1495. with tests.user_set(self.app.application, user):
  1496. output = self.app.get('/test/diff/master..feature')
  1497. self.assertEqual(output.status_code, 200)
  1498. self.assertIn(
  1499. '<title>Diff from feature to master - test\n - '
  1500. 'Pagure</title>', output.data)
  1501. self.assertIn(
  1502. '</button>\n This project enforces the '
  1503. 'Signed-off-by statement on all commits', output.data)
  1504. self.assertNotIn(
  1505. '<input type="submit" class="btn btn-primary" value="Create">',
  1506. output.data)
  1507. self.assertNotIn(
  1508. '</button>\n This repo enforces that '
  1509. 'all commits are signed off by their author.', output.data)
  1510. @patch('pagure.lib.notify.send_email')
  1511. def test_new_request_pull_req_sign_off_submit(self, send_email):
  1512. """ Test the new_request_pull endpoint. """
  1513. send_email.return_value = True
  1514. self.test_fork_project()
  1515. tests.create_projects_git(
  1516. os.path.join(self.path, 'requests'), bare=True)
  1517. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1518. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1519. # Enforce Signed-of-by in the repo
  1520. settings = repo.settings
  1521. settings['Enforce_signed-off_commits_in_pull-request'] = True
  1522. repo.settings = settings
  1523. self.session.add(repo)
  1524. self.session.commit()
  1525. self.set_up_git_repo(
  1526. new_project=fork, branch_from='feature', mtype='FF')
  1527. user = tests.FakeUser()
  1528. user.username = 'pingou'
  1529. with tests.user_set(self.app.application, user):
  1530. output = self.app.get('/test/diff/master..feature')
  1531. self.assertEqual(output.status_code, 200)
  1532. self.assertIn(
  1533. '<title>Create new Pull Request for master - test\n - '
  1534. 'Pagure</title>', output.data)
  1535. self.assertIn(
  1536. '</button>\n This project enforces the '
  1537. 'Signed-off-by statement on all commits', output.data)
  1538. self.assertIn(
  1539. '<input type="submit" class="btn btn-primary" value="Create">',
  1540. output.data)
  1541. csrf_token = self.get_csrf(output=output)
  1542. # Try to create the PR
  1543. data = {
  1544. 'csrf_token': csrf_token,
  1545. 'title': 'foo bar PR',
  1546. 'initial_comment': 'Test Initial Comment',
  1547. }
  1548. output = self.app.post(
  1549. '/test/diff/master..feature', data=data, follow_redirects=True)
  1550. self.assertEqual(output.status_code, 200)
  1551. self.assertIn(
  1552. '<title>Create new Pull Request for master - test\n - '
  1553. 'Pagure</title>', output.data)
  1554. # Flashed information message
  1555. self.assertIn(
  1556. '</button>\n This project enforces the '
  1557. 'Signed-off-by statement on all commits', output.data)
  1558. # Flashed error message
  1559. self.assertIn(
  1560. '</button>\n This repo enforces that '
  1561. 'all commits are signed off by their author.', output.data)
  1562. self.assertIn(
  1563. '<input type="submit" class="btn btn-primary" value="Create">',
  1564. output.data)
  1565. @patch('pagure.lib.notify.send_email')
  1566. def test_request_pull_commit_start_stop(self, send_email):
  1567. """ Test the the commit start and stop of brand new PR. """
  1568. send_email.return_value = True
  1569. self.test_fork_project()
  1570. tests.create_projects_git(
  1571. os.path.join(self.path, 'requests'), bare=True)
  1572. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1573. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1574. self.set_up_git_repo(
  1575. new_project=fork, branch_from='feature', mtype='FF')
  1576. user = tests.FakeUser()
  1577. user.username = 'pingou'
  1578. with tests.user_set(self.app.application, user):
  1579. output = self.app.get('/test/diff/master..feature')
  1580. self.assertEqual(output.status_code, 200)
  1581. self.assertIn(
  1582. '<title>Create new Pull Request for master - test\n - '
  1583. 'Pagure</title>', output.data)
  1584. self.assertIn(
  1585. '<input type="submit" class="btn btn-primary" value="Create">',
  1586. output.data)
  1587. csrf_token = self.get_csrf(output=output)
  1588. # Case 1 - Add an initial comment
  1589. data = {
  1590. 'csrf_token': csrf_token,
  1591. 'title': 'foo bar PR',
  1592. 'initial_comment': 'Test Initial Comment',
  1593. }
  1594. output = self.app.post(
  1595. '/test/diff/master..feature', data=data, follow_redirects=True)
  1596. self.assertEqual(output.status_code, 200)
  1597. self.assertIn(
  1598. '<title>PR#2: foo bar PR - test\n - Pagure</title>',
  1599. output.data)
  1600. self.assertIn('<p>Test Initial Comment</p>', output.data)
  1601. # Check if commit start and stop have been set for PR#2
  1602. request = pagure.lib.search_pull_requests(
  1603. self.session, project_id=1, requestid=2)
  1604. self.assertIsNotNone(request.commit_start)
  1605. self.assertIsNotNone(request.commit_stop)
  1606. @patch('pagure.lib.notify.send_email')
  1607. def test_new_request_pull_fork_to_fork_pr_disabled(self, send_email):
  1608. """ Test creating a fork to fork PR. """
  1609. send_email.return_value = True
  1610. self.test_fork_project()
  1611. # Create a 3rd user
  1612. item = pagure.lib.model.User(
  1613. user='ralph',
  1614. fullname='Ralph bar',
  1615. password='ralph_foo',
  1616. default_email='ralph@bar.com',
  1617. )
  1618. self.session.add(item)
  1619. item = pagure.lib.model.UserEmail(
  1620. user_id=3,
  1621. email='ralph@bar.com')
  1622. self.session.add(item)
  1623. self.session.commit()
  1624. user = tests.FakeUser()
  1625. user.username = 'ralph'
  1626. with tests.user_set(self.app.application, user):
  1627. # Have Ralph fork, foo's fork of test
  1628. output = self.app.get('/fork/foo/test')
  1629. self.assertEqual(output.status_code, 200)
  1630. output = self.app.post('/do_fork/fork/foo/test')
  1631. self.assertEqual(output.status_code, 400)
  1632. csrf_token = self.get_csrf()
  1633. data = {
  1634. 'csrf_token': csrf_token,
  1635. }
  1636. output = self.app.post(
  1637. '/do_fork/fork/foo/test', data=data,
  1638. follow_redirects=True)
  1639. self.assertEqual(output.status_code, 200)
  1640. # Check that Ralph's fork do exist
  1641. output = self.app.get('/fork/ralph/test')
  1642. self.assertEqual(output.status_code, 200)
  1643. tests.create_projects_git(
  1644. os.path.join(self.path, 'requests'), bare=True)
  1645. fork = pagure.lib.get_authorized_project(
  1646. self.session, 'test', user='ralph')
  1647. self.set_up_git_repo(
  1648. new_project=fork, branch_from='feature', mtype='FF')
  1649. # Try opening a pull-request
  1650. output = self.app.get(
  1651. '/fork/ralph/test/diff/master..feature')
  1652. self.assertEqual(output.status_code, 404)
  1653. self.assertIn(
  1654. u'<p>No pull-request allowed on this project</p>',
  1655. output.data)
  1656. @patch('pagure.lib.notify.send_email')
  1657. def test_new_request_pull_fork_to_fork(self, send_email):
  1658. """ Test creating a fork to fork PR. """
  1659. send_email.return_value = True
  1660. self.test_fork_project()
  1661. # Create a 3rd user
  1662. item = pagure.lib.model.User(
  1663. user='ralph',
  1664. fullname='Ralph bar',
  1665. password='ralph_foo',
  1666. default_email='ralph@bar.com',
  1667. )
  1668. self.session.add(item)
  1669. item = pagure.lib.model.UserEmail(
  1670. user_id=3,
  1671. email='ralph@bar.com')
  1672. self.session.add(item)
  1673. self.session.commit()
  1674. user = tests.FakeUser()
  1675. user.username = 'ralph'
  1676. with tests.user_set(self.app.application, user):
  1677. # Have Ralph fork, foo's fork of test
  1678. output = self.app.get('/fork/foo/test')
  1679. self.assertEqual(output.status_code, 200)
  1680. output = self.app.post('/do_fork/fork/foo/test')
  1681. self.assertEqual(output.status_code, 400)
  1682. csrf_token = self.get_csrf()
  1683. data = {
  1684. 'csrf_token': csrf_token,
  1685. }
  1686. output = self.app.post(
  1687. '/do_fork/fork/foo/test', data=data,
  1688. follow_redirects=True)
  1689. self.assertEqual(output.status_code, 200)
  1690. # Check that Ralph's fork do exist
  1691. output = self.app.get('/fork/ralph/test')
  1692. self.assertEqual(output.status_code, 200)
  1693. tests.create_projects_git(
  1694. os.path.join(self.path, 'requests'), bare=True)
  1695. # Turn on pull-request on the fork
  1696. repo = pagure.lib.get_authorized_project(
  1697. self.session, 'test', user='foo')
  1698. settings = repo.settings
  1699. settings['pull_requests'] = True
  1700. repo.settings = settings
  1701. self.session.add(repo)
  1702. self.session.commit()
  1703. # Add some content to the parent
  1704. self.set_up_git_repo(
  1705. new_project=repo, branch_from='master', mtype='FF',
  1706. name_from=repo.fullname)
  1707. fork = pagure.lib.get_authorized_project(
  1708. self.session, 'test', user='ralph')
  1709. self.set_up_git_repo(
  1710. new_project=fork, branch_from='feature', mtype='FF',
  1711. prid=2, name_from=fork.fullname)
  1712. # Try opening a pull-request
  1713. output = self.app.get(
  1714. '/fork/ralph/test/diff/master..feature')
  1715. self.assertEqual(output.status_code, 200)
  1716. self.assertIn(
  1717. '<title>Create new Pull Request for master - fork/ralph/test\n - '
  1718. 'Pagure</title>', output.data)
  1719. self.assertIn(
  1720. '<input type="submit" class="btn btn-primary" value="Create">',
  1721. output.data)
  1722. csrf_token = self.get_csrf(output=output)
  1723. # Case 1 - Add an initial comment
  1724. data = {
  1725. 'csrf_token': csrf_token,
  1726. 'title': 'foo bar PR',
  1727. 'initial_comment': 'Test Initial Comment',
  1728. }
  1729. output = self.app.post(
  1730. '/fork/ralph/test/diff/master..feature',
  1731. data=data, follow_redirects=True)
  1732. self.assertEqual(output.status_code, 200)
  1733. self.assertIn(
  1734. '<title>PR#1: foo bar PR - fork/foo/test\n - Pagure</title>',
  1735. output.data)
  1736. self.assertIn('<p>Test Initial Comment</p>', output.data)
  1737. @patch('pagure.lib.notify.send_email')
  1738. def test_new_request_pull_fork_to_other_fork(self, send_email):
  1739. """ Test creating a PR from fork to a fork of the same family. """
  1740. send_email.return_value = True
  1741. self.test_fork_project()
  1742. # Create a 3rd user
  1743. item = pagure.lib.model.User(
  1744. user='ralph',
  1745. fullname='Ralph bar',
  1746. password='ralph_foo',
  1747. default_email='ralph@bar.com',
  1748. )
  1749. self.session.add(item)
  1750. item = pagure.lib.model.UserEmail(
  1751. user_id=3,
  1752. email='ralph@bar.com')
  1753. self.session.add(item)
  1754. self.session.commit()
  1755. user = tests.FakeUser()
  1756. user.username = 'ralph'
  1757. with tests.user_set(self.app.application, user):
  1758. csrf_token = self.get_csrf()
  1759. data = {
  1760. 'csrf_token': csrf_token,
  1761. }
  1762. output = self.app.post(
  1763. '/do_fork/test', data=data,
  1764. follow_redirects=True)
  1765. self.assertEqual(output.status_code, 200)
  1766. # Check that Ralph's fork do exist
  1767. output = self.app.get('/fork/ralph/test')
  1768. self.assertEqual(output.status_code, 200)
  1769. tests.create_projects_git(
  1770. os.path.join(self.path, 'requests'), bare=True)
  1771. # Turn on pull-request on the fork
  1772. repo = pagure.lib.get_authorized_project(
  1773. self.session, 'test', user='foo')
  1774. settings = repo.settings
  1775. settings['pull_requests'] = True
  1776. repo.settings = settings
  1777. self.session.add(repo)
  1778. self.session.commit()
  1779. # Add some content to the parents
  1780. self.set_up_git_repo(
  1781. new_project=repo, branch_from='master', mtype='FF')
  1782. self.set_up_git_repo(
  1783. new_project=repo, branch_from='master', mtype='FF',
  1784. name_from=repo.fullname, prid=2)
  1785. fork = pagure.lib.get_authorized_project(
  1786. self.session, 'test', user='ralph')
  1787. self.set_up_git_repo(
  1788. new_project=fork, branch_from='feature', mtype='FF',
  1789. prid=3, name_from=fork.fullname)
  1790. # Try opening a pull-request
  1791. output = self.app.get(
  1792. '/fork/ralph/test/diff/master..feature?project_to=fork/foo/test')
  1793. self.assertEqual(output.status_code, 200)
  1794. self.assertIn(
  1795. '<title>Create new Pull Request for master - fork/ralph/test\n - '
  1796. 'Pagure</title>', output.data)
  1797. self.assertIn(
  1798. '<input type="submit" class="btn btn-primary" value="Create">',
  1799. output.data)
  1800. csrf_token = self.get_csrf(output=output)
  1801. # Case 1 - Opening PR to fork/foo/test
  1802. data = {
  1803. 'csrf_token': csrf_token,
  1804. 'title': 'foo bar PR',
  1805. 'initial_comment': 'Test Initial Comment',
  1806. }
  1807. output = self.app.post(
  1808. '/fork/ralph/test/diff/master..feature?project_to=fork/foo/test',
  1809. data=data, follow_redirects=True)
  1810. self.assertEqual(output.status_code, 200)
  1811. self.assertIn(
  1812. '<title>PR#1: foo bar PR - fork/foo/test\n - Pagure</title>',
  1813. output.data)
  1814. self.assertIn('<p>Test Initial Comment</p>', output.data)
  1815. # Case 1 - Opening PR to parent repo, shows project_to works
  1816. output = self.app.post(
  1817. '/fork/ralph/test/diff/master..feature',
  1818. data=data, follow_redirects=True)
  1819. self.assertEqual(output.status_code, 200)
  1820. self.assertIn(
  1821. '<title>PR#4: foo bar PR - test\n - Pagure</title>',
  1822. output.data)
  1823. self.assertIn('<p>Test Initial Comment</p>', output.data)
  1824. @patch('pagure.lib.notify.send_email')
  1825. def test_new_request_pull_fork_to_other_unrelated_fork(self, send_email):
  1826. """ Test creating a PR from fork to fork that isn't from the same
  1827. family.
  1828. """
  1829. send_email.return_value = True
  1830. self.test_fork_project()
  1831. # Create a 3rd user
  1832. item = pagure.lib.model.User(
  1833. user='ralph',
  1834. fullname='Ralph bar',
  1835. password='ralph_foo',
  1836. default_email='ralph@bar.com',
  1837. )
  1838. self.session.add(item)
  1839. item = pagure.lib.model.UserEmail(
  1840. user_id=3,
  1841. email='ralph@bar.com')
  1842. self.session.add(item)
  1843. self.session.commit()
  1844. user = tests.FakeUser()
  1845. user.username = 'ralph'
  1846. with tests.user_set(self.app.application, user):
  1847. csrf_token = self.get_csrf()
  1848. data = {
  1849. 'csrf_token': csrf_token,
  1850. }
  1851. output = self.app.post(
  1852. '/do_fork/test2', data=data,
  1853. follow_redirects=True)
  1854. self.assertEqual(output.status_code, 200)
  1855. # Check that Ralph's fork do exist
  1856. output = self.app.get('/fork/ralph/test2')
  1857. self.assertEqual(output.status_code, 200)
  1858. tests.create_projects_git(
  1859. os.path.join(self.path, 'requests'), bare=True)
  1860. # Turn on pull-request on the fork
  1861. repo = pagure.lib.get_authorized_project(
  1862. self.session, 'test', user='foo')
  1863. settings = repo.settings
  1864. settings['pull_requests'] = True
  1865. repo.settings = settings
  1866. self.session.add(repo)
  1867. self.session.commit()
  1868. # Add some content to the parent
  1869. self.set_up_git_repo(
  1870. new_project=repo, branch_from='master', mtype='FF',
  1871. name_from=repo.fullname)
  1872. fork = pagure.lib.get_authorized_project(
  1873. self.session, 'test2', user='ralph')
  1874. self.set_up_git_repo(
  1875. new_project=fork, branch_from='feature', mtype='FF',
  1876. prid=2, name_from=fork.fullname)
  1877. # Case 1 - Opening PR to fork/foo/test
  1878. data = {
  1879. 'csrf_token': csrf_token,
  1880. 'title': 'foo bar PR',
  1881. 'initial_comment': 'Test Initial Comment',
  1882. }
  1883. output = self.app.post(
  1884. '/fork/ralph/test2/diff/master..feature?project_to=fork/foo/test',
  1885. data=data, follow_redirects=True)
  1886. self.assertEqual(output.status_code, 400)
  1887. self.assertIn(
  1888. u"<p>fork/foo/test is not part of fork/ralph/test2's "
  1889. u"family</p>", output.data)
  1890. @patch('pagure.lib.notify.send_email')
  1891. def test_new_request_pull_empty_repo(self, send_email):
  1892. """ Test the new_request_pull endpoint against an empty repo. """
  1893. send_email.return_value = True
  1894. self.test_fork_project()
  1895. tests.create_projects_git(
  1896. os.path.join(self.path, 'requests'), bare=True)
  1897. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1898. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1899. # Create a git repo to play with
  1900. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1901. repo = pygit2.init_repository(gitrepo, bare=True)
  1902. # Create a fork of this repo
  1903. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  1904. gitrepo = os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git')
  1905. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1906. user = tests.FakeUser()
  1907. user.username = 'foo'
  1908. with tests.user_set(self.app.application, user):
  1909. output = self.app.get(
  1910. '/fork/foo/test/diff/master..feature',
  1911. follow_redirects=True)
  1912. self.assertEqual(output.status_code, 400)
  1913. self.assertIn(
  1914. u'<p>Fork is empty, there are no commits to create a pull '
  1915. u'request with</p>', output.data)
  1916. output = self.app.get('/test/new_issue')
  1917. csrf_token = self.get_csrf(output=output)
  1918. data = {
  1919. 'csrf_token': csrf_token,
  1920. 'title': 'foo bar PR',
  1921. }
  1922. output = self.app.post(
  1923. '/test/diff/master..feature', data=data, follow_redirects=True)
  1924. self.assertEqual(output.status_code, 400)
  1925. self.assertIn(
  1926. u'<p>Fork is empty, there are no commits to create a pull '
  1927. u'request with</p>', output.data)
  1928. shutil.rmtree(newpath)
  1929. @patch('pagure.lib.notify.send_email')
  1930. def test_new_request_pull_empty_fork(self, send_email):
  1931. """ Test the new_request_pull endpoint against an empty repo. """
  1932. send_email.return_value = True
  1933. self.test_fork_project()
  1934. tests.create_projects_git(
  1935. os.path.join(self.path, 'requests'), bare=True)
  1936. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1937. fork = pagure.lib.get_authorized_project(self.session, 'test', user='foo')
  1938. # Create a git repo to play with
  1939. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  1940. repo = pygit2.init_repository(gitrepo, bare=True)
  1941. # Create a fork of this repo
  1942. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  1943. gitrepo = os.path.join(
  1944. self.path, 'repos', 'forks', 'foo', 'test.git')
  1945. new_repo = pygit2.clone_repository(gitrepo, newpath)
  1946. user = tests.FakeUser()
  1947. user.username = 'foo'
  1948. with tests.user_set(self.app.application, user):
  1949. output = self.app.get(
  1950. '/fork/foo/test/diff/master..master', follow_redirects=True)
  1951. self.assertEqual(output.status_code, 400)
  1952. self.assertIn(
  1953. u'<p>Fork is empty, there are no commits to create a pull '
  1954. u'request with</p>', output.data)
  1955. shutil.rmtree(newpath)
  1956. @patch('pagure.lib.notify.send_email')
  1957. def test_pull_request_add_comment(self, send_email):
  1958. """ Test the pull_request_add_comment endpoint. """
  1959. send_email.return_value = True
  1960. self.test_request_pull()
  1961. user = tests.FakeUser()
  1962. user.username = 'pingou'
  1963. with tests.user_set(self.app.application, user):
  1964. output = self.app.post('/foo/pull-request/1/comment')
  1965. self.assertEqual(output.status_code, 404)
  1966. output = self.app.post('/test/pull-request/100/comment')
  1967. self.assertEqual(output.status_code, 404)
  1968. output = self.app.post('/test/pull-request/1/comment')
  1969. self.assertEqual(output.status_code, 200)
  1970. self.assertTrue(
  1971. output.data.startswith('\n<section class="add_comment">'))
  1972. csrf_token = self.get_csrf(output=output)
  1973. data = {
  1974. 'csrf_token': csrf_token,
  1975. 'comment': 'This look alright but we can do better',
  1976. }
  1977. output = self.app.post(
  1978. '/test/pull-request/1/comment', data=data,
  1979. follow_redirects=True)
  1980. self.assertEqual(output.status_code, 200)
  1981. self.assertIn(
  1982. '<title>PR#1: PR from the feature branch - test\n - '
  1983. 'Pagure</title>', output.data)
  1984. self.assertIn(
  1985. '</button>\n Comment added',
  1986. output.data)
  1987. self.assertEqual(output.data.count('title="PY C (pingou)"'), 2)
  1988. # Project w/o pull-request
  1989. repo = pagure.lib.get_authorized_project(self.session, 'test')
  1990. settings = repo.settings
  1991. settings['pull_requests'] = False
  1992. repo.settings = settings
  1993. self.session.add(repo)
  1994. self.session.commit()
  1995. output = self.app.post(
  1996. '/test/pull-request/1/comment', data=data,
  1997. follow_redirects=True)
  1998. self.assertEqual(output.status_code, 404)
  1999. @patch('pagure.lib.notify.send_email')
  2000. def test_pull_request_drop_comment(self, send_email):
  2001. """ Test the pull_request_drop_comment endpoint. """
  2002. send_email.return_value = True
  2003. self.test_pull_request_add_comment()
  2004. # Project w/ pull-request
  2005. repo = pagure.lib.get_authorized_project(self.session, 'test')
  2006. settings = repo.settings
  2007. settings['pull_requests'] = True
  2008. repo.settings = settings
  2009. self.session.add(repo)
  2010. self.session.commit()
  2011. user = tests.FakeUser()
  2012. user.username = 'foo'
  2013. with tests.user_set(self.app.application, user):
  2014. output = self.app.post('/foo/pull-request/1/comment/drop')
  2015. self.assertEqual(output.status_code, 404)
  2016. output = self.app.post('/test/pull-request/100/comment/drop')
  2017. self.assertEqual(output.status_code, 404)
  2018. output = self.app.post(
  2019. '/test/pull-request/1/comment/drop', follow_redirects=True)
  2020. self.assertEqual(output.status_code, 200)
  2021. self.assertIn(
  2022. '<h3><span class="label label-default">PR#1</span>\n'
  2023. ' PR from the feature branch\n</h3>', output.data)
  2024. #self.assertIn('href="#comment-1">¶</a>', output.data)
  2025. self.assertIn(
  2026. '<p>This look alright but we can do better</p>',
  2027. output.data)
  2028. csrf_token = self.get_csrf(output=output)
  2029. # Invalid comment id
  2030. data = {
  2031. 'csrf_token': csrf_token,
  2032. 'drop_comment': '10',
  2033. }
  2034. output = self.app.post(
  2035. '/test/pull-request/1/comment/drop', data=data,
  2036. follow_redirects=True)
  2037. self.assertEqual(output.status_code, 404)
  2038. data['drop_comment'] = '1'
  2039. output = self.app.post(
  2040. '/test/pull-request/1/comment/drop', data=data,
  2041. follow_redirects=True)
  2042. self.assertEqual(output.status_code, 403)
  2043. user.username = 'pingou'
  2044. with tests.user_set(self.app.application, user):
  2045. # Drop comment
  2046. output = self.app.post(
  2047. '/test/pull-request/1/comment/drop', data=data,
  2048. follow_redirects=True)
  2049. self.assertEqual(output.status_code, 200)
  2050. self.assertIn(
  2051. '<h3><span class="label label-default">PR#1</span>\n'
  2052. ' PR from the feature branch\n <span class="pull-xs-right">',
  2053. output.data)
  2054. self.assertIn(
  2055. '</button>\n Comment removed',
  2056. output.data)
  2057. # Project w/o pull-request
  2058. repo = pagure.lib.get_authorized_project(self.session, 'test')
  2059. settings = repo.settings
  2060. settings['pull_requests'] = False
  2061. repo.settings = settings
  2062. self.session.add(repo)
  2063. self.session.commit()
  2064. output = self.app.post(
  2065. '/test/pull-request/1/comment/drop', data=data,
  2066. follow_redirects=True)
  2067. self.assertEqual(output.status_code, 404)
  2068. @patch('pagure.lib.notify.send_email')
  2069. def test_pull_request_edit_comment(self, send_email):
  2070. """ Test the pull request edit comment endpoint """
  2071. send_email.return_value = True
  2072. self.test_request_pull()
  2073. user = tests.FakeUser()
  2074. user.username = 'pingou'
  2075. with tests.user_set(self.app.application, user):
  2076. # Repo 'foo' does not exist so it is verifying that condition
  2077. output = self.app.post('/foo/pull-request/1/comment/1/edit')
  2078. self.assertEqual(output.status_code, 404)
  2079. # Here no comment is present in the PR so its verifying that condition
  2080. output = self.app.post('/test/pull-request/100/comment/100/edit')
  2081. self.assertEqual(output.status_code, 404)
  2082. output = self.app.post('/test/pull-request/1/comment')
  2083. self.assertEqual(output.status_code, 200)
  2084. # Creating comment to play with
  2085. self.assertTrue(
  2086. output.data.startswith('\n<section class="add_comment">'))
  2087. csrf_token = self.get_csrf(output=output)
  2088. data = {
  2089. 'csrf_token': csrf_token,
  2090. 'comment': 'This look alright but we can do better',
  2091. }
  2092. output = self.app.post(
  2093. '/test/pull-request/1/comment', data=data,
  2094. follow_redirects=True)
  2095. self.assertEqual(output.status_code, 200)
  2096. self.assertIn(
  2097. '<h3><span class="label label-default">PR#1</span>\n'
  2098. ' PR from the feature branch\n <span class="pull-xs-right">',
  2099. output.data)
  2100. self.assertIn(
  2101. '</button>\n Comment added',
  2102. output.data)
  2103. # Check if the comment is there
  2104. self.assertIn(
  2105. '<p>This look alright but we can do better</p>', output.data)
  2106. output = self.app.get('/test/pull-request/1/comment/1/edit')
  2107. self.assertEqual(output.status_code, 200)
  2108. self.assertIn('<section class="edit_comment">', output.data)
  2109. # Checking if the comment is there in the update page
  2110. self.assertIn(
  2111. 'This look alright but we can do better</textarea>', output.data)
  2112. csrf_token = self.get_csrf(output=output)
  2113. data = {
  2114. 'csrf_token': csrf_token,
  2115. 'update_comment': 'This look alright but we can do better than this.',
  2116. }
  2117. output = self.app.post(
  2118. '/test/pull-request/1/comment/1/edit', data=data,
  2119. follow_redirects=True)
  2120. # Checking if the comment is updated in the main page
  2121. self.assertIn(
  2122. '<p>This look alright but we can do better than this.</p>', output.data)
  2123. self.assertIn(
  2124. '<h3><span class="label label-default">PR#1</span>\n'
  2125. ' PR from the feature branch\n <span class="pull-xs-right">',
  2126. output.data)
  2127. # Checking if Edited by User is there or not
  2128. self.assertTrue(
  2129. '<small class="text-muted">Edited just now by pingou </small>'
  2130. in output.data
  2131. or
  2132. '<small class="text-muted">Edited seconds ago by pingou </small>'
  2133. in output.data)
  2134. self.assertIn(
  2135. '</button>\n Comment updated', output.data)
  2136. # Project w/o pull-request
  2137. repo = pagure.lib.get_authorized_project(self.session, 'test')
  2138. settings = repo.settings
  2139. settings['pull_requests'] = False
  2140. repo.settings = settings
  2141. self.session.add(repo)
  2142. self.session.commit()
  2143. output = self.app.post(
  2144. '/test/pull-request/1/comment/edit/1', data=data,
  2145. follow_redirects=True)
  2146. self.assertEqual(output.status_code, 404)
  2147. @patch('pagure.lib.notify.send_email')
  2148. def test_merge_request_pull_FF_w_merge_commit(self, send_email):
  2149. """ Test the merge_request_pull endpoint with a FF PR but with a
  2150. merge commit.
  2151. """
  2152. send_email.return_value = True
  2153. self.test_request_pull()
  2154. user = tests.FakeUser()
  2155. with tests.user_set(self.app.application, user):
  2156. output = self.app.get('/test/pull-request/1')
  2157. self.assertEqual(output.status_code, 200)
  2158. csrf_token = self.get_csrf(output=output)
  2159. # No CSRF
  2160. output = self.app.post(
  2161. '/test/pull-request/1/merge', data={}, follow_redirects=True)
  2162. self.assertEqual(output.status_code, 200)
  2163. self.assertIn(
  2164. '<title>PR#1: PR from the feature branch - test\n - '
  2165. 'Pagure</title>', output.data)
  2166. self.assertIn(
  2167. '<h3><span class="label label-default">PR#1</span>\n'
  2168. ' PR from the feature branch\n</h3>', output.data)
  2169. self.assertIn(
  2170. 'title="View file as of 2a552b">sources</a>', output.data)
  2171. # Wrong project
  2172. data = {
  2173. 'csrf_token': csrf_token,
  2174. }
  2175. output = self.app.post(
  2176. '/foobar/pull-request/100/merge', data=data, follow_redirects=True)
  2177. self.assertEqual(output.status_code, 404)
  2178. # Wrong project
  2179. data = {
  2180. 'csrf_token': csrf_token,
  2181. }
  2182. output = self.app.post(
  2183. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  2184. self.assertEqual(output.status_code, 403)
  2185. user.username = 'pingou'
  2186. with tests.user_set(self.app.application, user):
  2187. # Wrong request id
  2188. data = {
  2189. 'csrf_token': csrf_token,
  2190. }
  2191. output = self.app.post(
  2192. '/test/pull-request/100/merge', data=data, follow_redirects=True)
  2193. self.assertEqual(output.status_code, 404)
  2194. # Project requiring a merge commit
  2195. repo = pagure.lib.get_authorized_project(self.session, 'test')
  2196. settings = repo.settings
  2197. settings['always_merge'] = True
  2198. repo.settings = settings
  2199. self.session.add(repo)
  2200. self.session.commit()
  2201. # Merge
  2202. output = self.app.post(
  2203. '/test/pull-request/1/merge', data=data, follow_redirects=True)
  2204. self.assertEqual(output.status_code, 200)
  2205. self.assertIn(
  2206. '<title>Overview - test - Pagure</title>', output.data)
  2207. self.assertIn(
  2208. 'Merge #1 `PR from the feature branch`', output.data)
  2209. self.assertIn(
  2210. 'A commit on branch feature', output.data)
  2211. # Ensure we have the merge commit
  2212. commits = _get_commits(output.data)
  2213. self.assertEqual(commits, [
  2214. 'Merge #1 `PR from the feature branch`',
  2215. 'A commit on branch feature',
  2216. 'Add sources file for testing',
  2217. ])
  2218. # Check if the closing notification was added
  2219. output = self.app.get('/test/pull-request/1')
  2220. self.assertIn(
  2221. '<small><p>Pull-Request has been merged by pingou</p></small>',
  2222. output.data)
  2223. @patch('pagure.lib.notify.send_email')
  2224. def test_internal_endpoint_main_ahead(self, send_email):
  2225. """ Test the new_request_pull endpoint when the main repo is ahead
  2226. of the fork.
  2227. """
  2228. send_email.return_value = True
  2229. tests.create_projects(self.session)
  2230. tests.create_projects_git(
  2231. os.path.join(self.path, 'requests'), bare=True)
  2232. self.set_up_git_repo(
  2233. new_project=None,
  2234. branch_from='feature')
  2235. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  2236. repo = pygit2.init_repository(gitrepo, bare=True)
  2237. # Make the main repo be ahead of the fork
  2238. # First commit
  2239. newpath = tempfile.mkdtemp(prefix='pagure-test')
  2240. repopath = os.path.join(newpath, 'test')
  2241. clone_repo = pygit2.clone_repository(gitrepo, repopath)
  2242. # Create a file in that git repo
  2243. with open(os.path.join(repopath, 'testfile'), 'w') as stream:
  2244. stream.write('foo\n bar')
  2245. clone_repo.index.add('testfile')
  2246. clone_repo.index.write()
  2247. # Commits the files added
  2248. last_commit = clone_repo.revparse_single('HEAD')
  2249. tree = clone_repo.index.write_tree()
  2250. author = pygit2.Signature(
  2251. 'Alice Author', 'alice@authors.tld')
  2252. committer = pygit2.Signature(
  2253. 'Cecil Committer', 'cecil@committers.tld')
  2254. clone_repo.create_commit(
  2255. 'refs/heads/master', # the name of the reference to update
  2256. author,
  2257. committer,
  2258. 'Add testfile file for testing',
  2259. # binary string representing the tree object ID
  2260. tree,
  2261. # list of binary strings representing parents of the new commit
  2262. [last_commit.oid.hex]
  2263. )
  2264. # Second commit
  2265. with open(os.path.join(repopath, 'testfile'), 'a') as stream:
  2266. stream.write('\nfoo2\n bar2')
  2267. clone_repo.index.add('testfile')
  2268. clone_repo.index.write()
  2269. # Commits the files added
  2270. last_commit = clone_repo.revparse_single('HEAD')
  2271. tree = clone_repo.index.write_tree()
  2272. author = pygit2.Signature(
  2273. 'Alice Author', 'alice@authors.tld')
  2274. committer = pygit2.Signature(
  2275. 'Cecil Committer', 'cecil@committers.tld')
  2276. clone_repo.create_commit(
  2277. 'refs/heads/master', # the name of the reference to update
  2278. author,
  2279. committer,
  2280. 'Add a second commit to testfile for testing',
  2281. # binary string representing the tree object ID
  2282. tree,
  2283. # list of binary strings representing parents of the new commit
  2284. [last_commit.oid.hex]
  2285. )
  2286. # Third commit
  2287. with open(os.path.join(repopath, 'testfile'), 'a') as stream:
  2288. stream.write('\nfoo3\n bar3')
  2289. clone_repo.index.add('testfile')
  2290. clone_repo.index.write()
  2291. # Commits the files added
  2292. last_commit = clone_repo.revparse_single('HEAD')
  2293. tree = clone_repo.index.write_tree()
  2294. author = pygit2.Signature(
  2295. 'Alice Author', 'alice@authors.tld')
  2296. committer = pygit2.Signature(
  2297. 'Cecil Committer', 'cecil@committers.tld')
  2298. clone_repo.create_commit(
  2299. 'refs/heads/master', # the name of the reference to update
  2300. author,
  2301. committer,
  2302. 'Add a third commit to testfile for testing',
  2303. # binary string representing the tree object ID
  2304. tree,
  2305. # list of binary strings representing parents of the new commit
  2306. [last_commit.oid.hex]
  2307. )
  2308. refname = 'refs/heads/master:refs/heads/master'
  2309. ori_remote = clone_repo.remotes[0]
  2310. PagureRepo.push(ori_remote, refname)
  2311. shutil.rmtree(newpath)
  2312. user = tests.FakeUser()
  2313. user.username = 'foo'
  2314. with tests.user_set(self.app.application, user):
  2315. output = self.app.get('/new')
  2316. csrf_token = output.data.split(
  2317. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  2318. output = self.app.post(
  2319. '/pv/pull-request/ready',
  2320. data={'repo': 'test', 'csrf_token': csrf_token}
  2321. )
  2322. self.assertEqual(output.status_code, 200)
  2323. data = json.loads(output.data)
  2324. self.assertEqual(
  2325. data,
  2326. {
  2327. "code": "OK",
  2328. "message": {
  2329. "branch_w_pr": {
  2330. "feature": "test/pull-request/1"
  2331. },
  2332. "new_branch": {}
  2333. }
  2334. }
  2335. )
  2336. @patch('pagure.lib.notify.send_email')
  2337. def test_fork_edit_file(self, send_email):
  2338. """ Test the fork_edit file endpoint. """
  2339. send_email.return_value = True
  2340. # Git repo not found
  2341. output = self.app.post('fork_edit/test/edit/master/f/sources')
  2342. self.assertEqual(output.status_code, 404)
  2343. tests.create_projects(self.session)
  2344. for folder in ['docs', 'tickets', 'requests', 'repos']:
  2345. tests.create_projects_git(
  2346. os.path.join(self.path, folder), bare=True)
  2347. # User not logged in
  2348. output = self.app.post('fork_edit/test/edit/master/f/sources')
  2349. self.assertEqual(output.status_code, 302)
  2350. user = tests.FakeUser()
  2351. user.username = 'pingou'
  2352. with tests.user_set(self.app.application, user):
  2353. # Invalid request
  2354. output = self.app.post('fork_edit/test/edit/master/f/source')
  2355. self.assertEqual(output.status_code, 400)
  2356. output = self.app.get('/new/')
  2357. self.assertEqual(output.status_code, 200)
  2358. self.assertIn('<strong>Create new Project</strong>', output.data)
  2359. csrf_token = self.get_csrf(output=output)
  2360. data = {
  2361. 'csrf_token': csrf_token,
  2362. }
  2363. # No files can be found since they are not added
  2364. output = self.app.post('fork_edit/test/edit/master/f/sources',
  2365. data=data, follow_redirects=True)
  2366. self.assertEqual(output.status_code, 404)
  2367. user = tests.FakeUser()
  2368. user.username = 'foo'
  2369. with tests.user_set(self.app.application, user):
  2370. data = {
  2371. 'csrf_token': csrf_token,
  2372. }
  2373. # Invalid request
  2374. output = self.app.post('fork_edit/test/edit/master/f/sources',
  2375. follow_redirects=True)
  2376. self.assertEqual(output.status_code, 400)
  2377. # Add content to the repo
  2378. tests.add_content_git_repo(os.path.join(
  2379. pagure.config.config['GIT_FOLDER'], 'test.git'))
  2380. tests.add_readme_git_repo(os.path.join(
  2381. pagure.config.config['GIT_FOLDER'], 'test.git'))
  2382. tests.add_binary_git_repo(
  2383. os.path.join(
  2384. pagure.config.config['GIT_FOLDER'], 'test.git'), 'test.jpg')
  2385. # Check if button exists
  2386. output = self.app.get('/test/blob/master/f/sources')
  2387. self.assertEqual(output.status_code, 200)
  2388. self.assertIn(
  2389. 'Fork and Edit\n </button>\n',
  2390. output.data)
  2391. # Check fork-edit doesn't show for binary files
  2392. output = self.app.get('/test/blob/master/f/test.jpg')
  2393. self.assertEqual(output.status_code, 200)
  2394. self.assertNotIn(
  2395. 'Fork and Edit\n </button>\n',
  2396. output.data)
  2397. # Check for edit panel
  2398. output = self.app.post('fork_edit/test/edit/master/f/sources',
  2399. data=data, follow_redirects=True)
  2400. self.assertEqual(output.status_code, 200)
  2401. self.assertIn(
  2402. '<li><a href="/fork/foo/test/tree/master">'
  2403. '<span class="oi" data-glyph="random"></span>&nbsp; master</a>'
  2404. '</li><li class="active"><span class="oi" data-glyph="file">'
  2405. '</span>&nbsp; sources</li>',
  2406. output.data)
  2407. self.assertIn(
  2408. '<textarea id="textareaCode" name="content">foo\n bar</textarea>',
  2409. output.data)
  2410. # View what's supposed to be an image
  2411. output = self.app.post('fork_edit/test/edit/master/f/test.jpg',
  2412. data=data, follow_redirects=True)
  2413. self.assertEqual(output.status_code, 400)
  2414. self.assertIn('<p>Cannot edit binary files</p>', output.data)
  2415. # Check fork-edit shows when user is not logged in
  2416. output = self.app.get('/test/blob/master/f/sources')
  2417. self.assertEqual(output.status_code, 200)
  2418. self.assertIn(
  2419. 'Fork and Edit\n </button>\n',
  2420. output.data)
  2421. # Check if fork-edit shows for different user
  2422. user.username = 'pingou'
  2423. with tests.user_set(self.app.application, user):
  2424. # Check if button exists
  2425. output = self.app.get('/test/blob/master/f/sources')
  2426. self.assertEqual(output.status_code, 200)
  2427. self.assertIn(
  2428. 'Edit in your fork\n </button>\n',
  2429. output.data)
  2430. # Check fork-edit doesn't show for binary
  2431. output = self.app.get('/test/blob/master/f/test.jpg')
  2432. self.assertEqual(output.status_code, 200)
  2433. self.assertNotIn(
  2434. 'Edit in your fork\n </button>\n',
  2435. output.data)
  2436. @patch('pagure.lib.notify.send_email')
  2437. def test_fork_without_main_repo(self, send_email):
  2438. """ Test the fork without the main repo. """
  2439. send_email.return_value = True
  2440. tests.create_projects(self.session)
  2441. # Create a fork with no parent i.e parent_id = None
  2442. item = pagure.lib.model.Project(
  2443. user_id=2, # foo
  2444. name='test',
  2445. description='test project #1',
  2446. hook_token='aaabbb',
  2447. is_fork=True,
  2448. parent_id=None,
  2449. )
  2450. self.session.add(item)
  2451. self.session.commit()
  2452. # Get fork project
  2453. project = pagure.lib._get_project(self.session, 'test', 'foo')
  2454. # Pull-requests and issue-trackers are off for forks
  2455. # lib function is not used here so mannually turning them off
  2456. project_settings = project.settings
  2457. project_settings['pull_requests'] = False
  2458. project_settings['issue_tracker'] = False
  2459. project.settings = project_settings
  2460. self.session.add(project)
  2461. self.session.commit()
  2462. tests.create_projects_git(
  2463. os.path.join(self.path, 'repos', 'forks', 'foo'), bare=True)
  2464. # Create a git repo to play with
  2465. gitrepo = os.path.join(self.path, 'repos', 'test.git')
  2466. self.assertFalse(os.path.exists(gitrepo))
  2467. os.makedirs(gitrepo)
  2468. repo = pygit2.init_repository(gitrepo, bare=True)
  2469. # Create a fork of this repo
  2470. newpath = tempfile.mkdtemp(prefix='pagure-fork-test')
  2471. gitrepo = os.path.join(self.path, 'repos', 'forks', 'foo', 'test.git')
  2472. new_repo = pygit2.clone_repository(gitrepo, newpath)
  2473. tests.add_content_git_repo(gitrepo)
  2474. # UI test for deleted main
  2475. output = self.app.get('/fork/foo/test')
  2476. self.assertEqual(output.status_code, 200)
  2477. self.assertIn('Fork from a deleted repository\n', output.data)
  2478. # Testing commit endpoint
  2479. output = self.app.get('/fork/foo/test/commits/master')
  2480. self.assertEqual(output.status_code, 200)
  2481. self.assertIn('Commits <span class="label label-default"> 2</span>\n </h3>\n', output.data)
  2482. # Test pull-request endpoint
  2483. output = self.app.get('/fork/foo/test/pull-requests')
  2484. self.assertEqual(output.status_code, 404)
  2485. # Test issue-tracker endpoint
  2486. output = self.app.get('/fork/foo/test/issues')
  2487. self.assertEqual(output.status_code, 404)
  2488. shutil.rmtree(newpath)
  2489. if __name__ == '__main__':
  2490. unittest.main(verbosity=2)