1
0

test_pagure_lib_git.py 101 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals, absolute_import
  8. import datetime
  9. import os
  10. import shutil
  11. import sys
  12. import tempfile
  13. import time
  14. import unittest
  15. import pygit2
  16. import six
  17. from mock import patch, MagicMock
  18. sys.path.insert(0, os.path.join(os.path.dirname(
  19. os.path.abspath(__file__)), '..'))
  20. import pagure.lib.git
  21. import tests
  22. from pagure.lib.repo import PagureRepo
  23. class PagureLibGittests(tests.Modeltests):
  24. """ Tests for pagure.lib.git """
  25. def test_write_gitolite_acls(self):
  26. """ Test the write_gitolite_acls function of pagure.lib.git.
  27. when the new uesr is an made an admin """
  28. tests.create_projects(self.session)
  29. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  30. # Add an user to a project
  31. # The user will be an admin of the project
  32. msg = pagure.lib.query.add_user_to_project(
  33. session=self.session,
  34. project=repo,
  35. new_user='foo',
  36. user='pingou',
  37. )
  38. self.session.commit()
  39. self.assertEqual(msg, 'User added')
  40. # Add a forked project
  41. item = pagure.lib.model.Project(
  42. user_id=1, # pingou
  43. name='test3',
  44. description='test project #2',
  45. is_fork=True,
  46. parent_id=1,
  47. hook_token='aaabbbvvv',
  48. )
  49. self.session.add(item)
  50. self.session.commit()
  51. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  52. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  53. helper.write_gitolite_acls(
  54. self.session, configfile=outputconf, project=-1)
  55. self.assertTrue(os.path.exists(outputconf))
  56. with open(outputconf) as stream:
  57. data = stream.read()
  58. exp = """repo test
  59. R = @all
  60. RW+ = pingou
  61. RW+ = foo
  62. repo docs/test
  63. R = @all
  64. RW+ = pingou
  65. RW+ = foo
  66. repo tickets/test
  67. RW+ = pingou
  68. RW+ = foo
  69. repo requests/test
  70. RW+ = pingou
  71. RW+ = foo
  72. repo test2
  73. R = @all
  74. RW+ = pingou
  75. repo docs/test2
  76. R = @all
  77. RW+ = pingou
  78. repo tickets/test2
  79. RW+ = pingou
  80. repo requests/test2
  81. RW+ = pingou
  82. repo somenamespace/test3
  83. R = @all
  84. RW+ = pingou
  85. repo docs/somenamespace/test3
  86. R = @all
  87. RW+ = pingou
  88. repo tickets/somenamespace/test3
  89. RW+ = pingou
  90. repo requests/somenamespace/test3
  91. RW+ = pingou
  92. repo forks/pingou/test3
  93. R = @all
  94. RW+ = pingou
  95. repo docs/forks/pingou/test3
  96. R = @all
  97. RW+ = pingou
  98. repo tickets/forks/pingou/test3
  99. RW+ = pingou
  100. repo requests/forks/pingou/test3
  101. RW+ = pingou
  102. # end of body
  103. """
  104. #print data
  105. self.assertEqual(data, exp)
  106. os.unlink(outputconf)
  107. self.assertFalse(os.path.exists(outputconf))
  108. def test_write_gitolite_acls_preconf(self):
  109. """ Test the write_gitolite_acls function of pagure.lib.git with
  110. a preconf set """
  111. tests.create_projects(self.session)
  112. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  113. preconf = os.path.join(self.path, 'header_gitolite')
  114. with open(preconf, 'w') as stream:
  115. stream.write('# this is a header that is manually added')
  116. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  117. helper.write_gitolite_acls(
  118. self.session,
  119. outputconf,
  120. project=-1,
  121. preconf=preconf
  122. )
  123. self.assertTrue(os.path.exists(outputconf))
  124. with open(outputconf) as stream:
  125. data = stream.read()
  126. exp = """# this is a header that is manually added
  127. # end of header
  128. repo test
  129. R = @all
  130. RW+ = pingou
  131. repo docs/test
  132. R = @all
  133. RW+ = pingou
  134. repo tickets/test
  135. RW+ = pingou
  136. repo requests/test
  137. RW+ = pingou
  138. repo test2
  139. R = @all
  140. RW+ = pingou
  141. repo docs/test2
  142. R = @all
  143. RW+ = pingou
  144. repo tickets/test2
  145. RW+ = pingou
  146. repo requests/test2
  147. RW+ = pingou
  148. repo somenamespace/test3
  149. R = @all
  150. RW+ = pingou
  151. repo docs/somenamespace/test3
  152. R = @all
  153. RW+ = pingou
  154. repo tickets/somenamespace/test3
  155. RW+ = pingou
  156. repo requests/somenamespace/test3
  157. RW+ = pingou
  158. # end of body
  159. """
  160. #print data
  161. self.assertEqual(data.split('\n'), exp.split('\n'))
  162. os.unlink(outputconf)
  163. self.assertFalse(os.path.exists(outputconf))
  164. def test_write_gitolite_acls_preconf_postconf(self):
  165. """ Test the write_gitolite_acls function of pagure.lib.git with
  166. a postconf set """
  167. tests.create_projects(self.session)
  168. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  169. preconf = os.path.join(self.path, 'header_gitolite')
  170. with open(preconf, 'w') as stream:
  171. stream.write('# this is a header that is manually added')
  172. postconf = os.path.join(self.path, 'footer_gitolite')
  173. with open(postconf, 'w') as stream:
  174. stream.write('# end of generated configuration')
  175. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  176. helper.write_gitolite_acls(
  177. self.session,
  178. outputconf,
  179. project=-1,
  180. preconf=preconf,
  181. postconf=postconf
  182. )
  183. self.assertTrue(os.path.exists(outputconf))
  184. with open(outputconf) as stream:
  185. data = stream.read()
  186. exp = """# this is a header that is manually added
  187. # end of header
  188. repo test
  189. R = @all
  190. RW+ = pingou
  191. repo docs/test
  192. R = @all
  193. RW+ = pingou
  194. repo tickets/test
  195. RW+ = pingou
  196. repo requests/test
  197. RW+ = pingou
  198. repo test2
  199. R = @all
  200. RW+ = pingou
  201. repo docs/test2
  202. R = @all
  203. RW+ = pingou
  204. repo tickets/test2
  205. RW+ = pingou
  206. repo requests/test2
  207. RW+ = pingou
  208. repo somenamespace/test3
  209. R = @all
  210. RW+ = pingou
  211. repo docs/somenamespace/test3
  212. R = @all
  213. RW+ = pingou
  214. repo tickets/somenamespace/test3
  215. RW+ = pingou
  216. repo requests/somenamespace/test3
  217. RW+ = pingou
  218. # end of body
  219. # end of generated configuration
  220. """
  221. #print data
  222. self.assertEqual(data, exp)
  223. os.unlink(outputconf)
  224. self.assertFalse(os.path.exists(outputconf))
  225. def test_write_gitolite_acls_postconf(self):
  226. """ Test the write_gitolite_acls function of pagure.lib.git with
  227. a preconf and a postconf set """
  228. tests.create_projects(self.session)
  229. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  230. postconf = os.path.join(self.path, 'footer_gitolite')
  231. with open(postconf, 'w') as stream:
  232. stream.write('# end of generated configuration')
  233. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  234. helper.write_gitolite_acls(
  235. self.session,
  236. outputconf,
  237. project=-1,
  238. postconf=postconf
  239. )
  240. self.assertTrue(os.path.exists(outputconf))
  241. with open(outputconf) as stream:
  242. data = stream.read()
  243. exp = """repo test
  244. R = @all
  245. RW+ = pingou
  246. repo docs/test
  247. R = @all
  248. RW+ = pingou
  249. repo tickets/test
  250. RW+ = pingou
  251. repo requests/test
  252. RW+ = pingou
  253. repo test2
  254. R = @all
  255. RW+ = pingou
  256. repo docs/test2
  257. R = @all
  258. RW+ = pingou
  259. repo tickets/test2
  260. RW+ = pingou
  261. repo requests/test2
  262. RW+ = pingou
  263. repo somenamespace/test3
  264. R = @all
  265. RW+ = pingou
  266. repo docs/somenamespace/test3
  267. R = @all
  268. RW+ = pingou
  269. repo tickets/somenamespace/test3
  270. RW+ = pingou
  271. repo requests/somenamespace/test3
  272. RW+ = pingou
  273. # end of body
  274. # end of generated configuration
  275. """
  276. #print data
  277. self.assertEqual(data, exp)
  278. os.unlink(outputconf)
  279. self.assertFalse(os.path.exists(outputconf))
  280. def test_write_gitolite_acls_deploykeys(self):
  281. """ Test write_gitolite_acls function to add deploy keys. """
  282. tests.create_projects(self.session)
  283. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  284. # Add two deploy keys (one readonly one push)
  285. pingou = pagure.lib.query.get_user(self.session, 'pingou')
  286. msg1 = pagure.lib.query.add_sshkey_to_project_or_user(
  287. session=self.session,
  288. project=repo,
  289. ssh_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAzBMSIlvPRaEiLOTVInErkRIw9CzQQcnslDekAn1jFnGf+SNa1acvbTiATbCX71AA03giKrPxPH79dxcC7aDXerc6zRcKjJs6MAL9PrCjnbyxCKXRNNZU5U9X/DLaaL1b3caB+WD6OoorhS3LTEtKPX8xyjOzhf3OQSzNjhJp5Q==',
  290. pushaccess=False,
  291. creator=pingou
  292. )
  293. msg2 = pagure.lib.query.add_sshkey_to_project_or_user(
  294. session=self.session,
  295. project=repo,
  296. ssh_key='ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC9Xwc2RDzPBhlEDARfHldGjudIVoa04tqT1JVKGQmyllTFz7Rb8CngQL3e7zyNzotnhwYKHdoiLlPkVEiDee4dWMUe48ilqId+FJZQGhyv8fu4BoFdE1AJUVylzmltbLg14VqG5gjTpXgtlrEva9arKwBMHJjRYc8ScaSn3OgyQw==',
  297. pushaccess=True,
  298. creator=pingou
  299. )
  300. self.session.commit()
  301. self.assertEqual(msg1, 'SSH key added')
  302. self.assertEqual(msg2, 'SSH key added')
  303. # Add a forked project
  304. item = pagure.lib.model.Project(
  305. user_id=1, # pingou
  306. name='test3',
  307. description='test project #2',
  308. is_fork=True,
  309. parent_id=1,
  310. hook_token='aaabbbvvv',
  311. )
  312. self.session.add(item)
  313. self.session.commit()
  314. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  315. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  316. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  317. self.assertTrue(os.path.exists(outputconf))
  318. with open(outputconf) as stream:
  319. data = stream.read()
  320. exp = """repo test
  321. R = @all
  322. RW+ = pingou
  323. R = deploykey_test_1
  324. RW+ = deploykey_test_2
  325. repo docs/test
  326. R = @all
  327. RW+ = pingou
  328. R = deploykey_test_1
  329. RW+ = deploykey_test_2
  330. repo tickets/test
  331. RW+ = pingou
  332. R = deploykey_test_1
  333. RW+ = deploykey_test_2
  334. repo requests/test
  335. RW+ = pingou
  336. R = deploykey_test_1
  337. RW+ = deploykey_test_2
  338. repo test2
  339. R = @all
  340. RW+ = pingou
  341. repo docs/test2
  342. R = @all
  343. RW+ = pingou
  344. repo tickets/test2
  345. RW+ = pingou
  346. repo requests/test2
  347. RW+ = pingou
  348. repo somenamespace/test3
  349. R = @all
  350. RW+ = pingou
  351. repo docs/somenamespace/test3
  352. R = @all
  353. RW+ = pingou
  354. repo tickets/somenamespace/test3
  355. RW+ = pingou
  356. repo requests/somenamespace/test3
  357. RW+ = pingou
  358. repo forks/pingou/test3
  359. R = @all
  360. RW+ = pingou
  361. repo docs/forks/pingou/test3
  362. R = @all
  363. RW+ = pingou
  364. repo tickets/forks/pingou/test3
  365. RW+ = pingou
  366. repo requests/forks/pingou/test3
  367. RW+ = pingou
  368. # end of body
  369. """
  370. #print data
  371. self.assertEqual(data, exp)
  372. os.unlink(outputconf)
  373. self.assertFalse(os.path.exists(outputconf))
  374. def test_write_gitolite_acls_ticket(self):
  375. """ Test the write_gitolite_acls function of pagure.lib.git.
  376. when the new uesr is just a ticketer """
  377. tests.create_projects(self.session)
  378. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  379. # Add an user to a project
  380. # The user will be an admin of the project
  381. msg = pagure.lib.query.add_user_to_project(
  382. session=self.session,
  383. project=repo,
  384. new_user='foo',
  385. user='pingou',
  386. access='ticket'
  387. )
  388. self.session.commit()
  389. self.assertEqual(msg, 'User added')
  390. # Add a forked project
  391. item = pagure.lib.model.Project(
  392. user_id=1, # pingou
  393. name='test3',
  394. description='test project #2',
  395. is_fork=True,
  396. parent_id=1,
  397. hook_token='aaabbbvvv',
  398. )
  399. self.session.add(item)
  400. self.session.commit()
  401. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  402. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  403. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  404. self.assertTrue(os.path.exists(outputconf))
  405. with open(outputconf) as stream:
  406. data = stream.read()
  407. exp = """repo test
  408. R = @all
  409. RW+ = pingou
  410. repo docs/test
  411. R = @all
  412. RW+ = pingou
  413. repo tickets/test
  414. RW+ = pingou
  415. repo requests/test
  416. RW+ = pingou
  417. repo test2
  418. R = @all
  419. RW+ = pingou
  420. repo docs/test2
  421. R = @all
  422. RW+ = pingou
  423. repo tickets/test2
  424. RW+ = pingou
  425. repo requests/test2
  426. RW+ = pingou
  427. repo somenamespace/test3
  428. R = @all
  429. RW+ = pingou
  430. repo docs/somenamespace/test3
  431. R = @all
  432. RW+ = pingou
  433. repo tickets/somenamespace/test3
  434. RW+ = pingou
  435. repo requests/somenamespace/test3
  436. RW+ = pingou
  437. repo forks/pingou/test3
  438. R = @all
  439. RW+ = pingou
  440. repo docs/forks/pingou/test3
  441. R = @all
  442. RW+ = pingou
  443. repo tickets/forks/pingou/test3
  444. RW+ = pingou
  445. repo requests/forks/pingou/test3
  446. RW+ = pingou
  447. # end of body
  448. """
  449. #print data
  450. self.assertEqual(data, exp)
  451. os.unlink(outputconf)
  452. self.assertFalse(os.path.exists(outputconf))
  453. def test_write_gitolite_acls_commit(self):
  454. """ Test the write_gitolite_acls function of pagure.lib.git.
  455. when the new uesr is just a committer """
  456. tests.create_projects(self.session)
  457. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  458. # Add an user to a project
  459. # The user will be an admin of the project
  460. msg = pagure.lib.query.add_user_to_project(
  461. session=self.session,
  462. project=repo,
  463. new_user='foo',
  464. user='pingou',
  465. access='commit'
  466. )
  467. self.session.commit()
  468. self.assertEqual(msg, 'User added')
  469. # Add a forked project
  470. item = pagure.lib.model.Project(
  471. user_id=1, # pingou
  472. name='test3',
  473. description='test project #2',
  474. is_fork=True,
  475. parent_id=1,
  476. hook_token='aaabbbvvv',
  477. )
  478. self.session.add(item)
  479. self.session.commit()
  480. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  481. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  482. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  483. self.assertTrue(os.path.exists(outputconf))
  484. with open(outputconf) as stream:
  485. data = stream.read()
  486. exp = """repo test
  487. R = @all
  488. RW+ = pingou
  489. RW+ = foo
  490. repo docs/test
  491. R = @all
  492. RW+ = pingou
  493. RW+ = foo
  494. repo tickets/test
  495. RW+ = pingou
  496. RW+ = foo
  497. repo requests/test
  498. RW+ = pingou
  499. RW+ = foo
  500. repo test2
  501. R = @all
  502. RW+ = pingou
  503. repo docs/test2
  504. R = @all
  505. RW+ = pingou
  506. repo tickets/test2
  507. RW+ = pingou
  508. repo requests/test2
  509. RW+ = pingou
  510. repo somenamespace/test3
  511. R = @all
  512. RW+ = pingou
  513. repo docs/somenamespace/test3
  514. R = @all
  515. RW+ = pingou
  516. repo tickets/somenamespace/test3
  517. RW+ = pingou
  518. repo requests/somenamespace/test3
  519. RW+ = pingou
  520. repo forks/pingou/test3
  521. R = @all
  522. RW+ = pingou
  523. repo docs/forks/pingou/test3
  524. R = @all
  525. RW+ = pingou
  526. repo tickets/forks/pingou/test3
  527. RW+ = pingou
  528. repo requests/forks/pingou/test3
  529. RW+ = pingou
  530. # end of body
  531. """
  532. #print data
  533. self.assertEqual(data, exp)
  534. os.unlink(outputconf)
  535. self.assertFalse(os.path.exists(outputconf))
  536. def test_write_gitolite_acls_groups(self):
  537. """ Test the write_gitolite_acls function of pagure.lib.git with
  538. groups as admin
  539. """
  540. tests.create_projects(self.session)
  541. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  542. # Add a couple of groups
  543. # They would be admins
  544. msg = pagure.lib.query.add_group(
  545. self.session,
  546. group_name='sysadmin',
  547. display_name='sysadmin group',
  548. description=None,
  549. group_type='user',
  550. user='pingou',
  551. is_admin=False,
  552. blacklist=[],
  553. )
  554. self.session.commit()
  555. self.assertEqual(msg, 'User `pingou` added to the group `sysadmin`.')
  556. msg = pagure.lib.query.add_group(
  557. self.session,
  558. group_name='devs',
  559. display_name='devs group',
  560. description=None,
  561. group_type='user',
  562. user='pingou',
  563. is_admin=False,
  564. blacklist=[],
  565. )
  566. self.session.commit()
  567. self.assertEqual(msg, 'User `pingou` added to the group `devs`.')
  568. # Associate these groups to a project
  569. msg = pagure.lib.query.add_group_to_project(
  570. session=self.session,
  571. project=repo,
  572. new_group='sysadmin',
  573. user='pingou',
  574. )
  575. self.session.commit()
  576. self.assertEqual(msg, 'Group added')
  577. msg = pagure.lib.query.add_group_to_project(
  578. session=self.session,
  579. project=repo,
  580. new_group='devs',
  581. user='pingou',
  582. )
  583. self.session.commit()
  584. self.assertEqual(msg, 'Group added')
  585. # Add an user to a project
  586. msg = pagure.lib.query.add_user_to_project(
  587. session=self.session,
  588. project=repo,
  589. new_user='foo',
  590. user='pingou',
  591. )
  592. self.session.commit()
  593. self.assertEqual(msg, 'User added')
  594. # Add a forked project
  595. item = pagure.lib.model.Project(
  596. user_id=1, # pingou
  597. name='test2',
  598. description='test project #2',
  599. is_fork=True,
  600. parent_id=1,
  601. hook_token='aaabbbvvv',
  602. )
  603. self.session.add(item)
  604. self.session.commit()
  605. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  606. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  607. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  608. self.assertTrue(os.path.exists(outputconf))
  609. with open(outputconf) as stream:
  610. data = stream.read()
  611. exp = """@devs = pingou
  612. @sysadmin = pingou
  613. # end of groups
  614. repo test
  615. R = @all
  616. RW+ = @devs @sysadmin
  617. RW+ = pingou
  618. RW+ = foo
  619. repo docs/test
  620. R = @all
  621. RW+ = @devs @sysadmin
  622. RW+ = pingou
  623. RW+ = foo
  624. repo tickets/test
  625. RW+ = @devs @sysadmin
  626. RW+ = pingou
  627. RW+ = foo
  628. repo requests/test
  629. RW+ = @devs @sysadmin
  630. RW+ = pingou
  631. RW+ = foo
  632. repo test2
  633. R = @all
  634. RW+ = pingou
  635. repo docs/test2
  636. R = @all
  637. RW+ = pingou
  638. repo tickets/test2
  639. RW+ = pingou
  640. repo requests/test2
  641. RW+ = pingou
  642. repo somenamespace/test3
  643. R = @all
  644. RW+ = pingou
  645. repo docs/somenamespace/test3
  646. R = @all
  647. RW+ = pingou
  648. repo tickets/somenamespace/test3
  649. RW+ = pingou
  650. repo requests/somenamespace/test3
  651. RW+ = pingou
  652. repo forks/pingou/test2
  653. R = @all
  654. RW+ = pingou
  655. repo docs/forks/pingou/test2
  656. R = @all
  657. RW+ = pingou
  658. repo tickets/forks/pingou/test2
  659. RW+ = pingou
  660. repo requests/forks/pingou/test2
  661. RW+ = pingou
  662. # end of body
  663. """
  664. #print data
  665. self.assertEqual(data.split('\n'), exp.split('\n'))
  666. os.unlink(outputconf)
  667. self.assertFalse(os.path.exists(outputconf))
  668. def test_write_gitolite_acls_groups_ticket(self):
  669. """ Test the write_gitolite_acls function of pagure.lib.git with
  670. groups as ticketers
  671. """
  672. tests.create_projects(self.session)
  673. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  674. # Add a couple of groups
  675. # They would be ticketers
  676. msg = pagure.lib.query.add_group(
  677. self.session,
  678. group_name='sysadmin',
  679. display_name='sysadmin group',
  680. description=None,
  681. group_type='user',
  682. user='pingou',
  683. is_admin=False,
  684. blacklist=[],
  685. )
  686. self.session.commit()
  687. self.assertEqual(msg, 'User `pingou` added to the group `sysadmin`.')
  688. msg = pagure.lib.query.add_group(
  689. self.session,
  690. group_name='devs',
  691. display_name='devs group',
  692. description=None,
  693. group_type='user',
  694. user='pingou',
  695. is_admin=False,
  696. blacklist=[],
  697. )
  698. self.session.commit()
  699. self.assertEqual(msg, 'User `pingou` added to the group `devs`.')
  700. # Associate these groups to a project
  701. msg = pagure.lib.query.add_group_to_project(
  702. session=self.session,
  703. project=repo,
  704. new_group='sysadmin',
  705. user='pingou',
  706. access='ticket',
  707. )
  708. self.session.commit()
  709. self.assertEqual(msg, 'Group added')
  710. msg = pagure.lib.query.add_group_to_project(
  711. session=self.session,
  712. project=repo,
  713. new_group='devs',
  714. user='pingou',
  715. access='ticket'
  716. )
  717. self.session.commit()
  718. self.assertEqual(msg, 'Group added')
  719. # Add an user to a project
  720. msg = pagure.lib.query.add_user_to_project(
  721. session=self.session,
  722. project=repo,
  723. new_user='foo',
  724. user='pingou',
  725. )
  726. self.session.commit()
  727. self.assertEqual(msg, 'User added')
  728. # Add a forked project
  729. item = pagure.lib.model.Project(
  730. user_id=1, # pingou
  731. name='test2',
  732. description='test project #2',
  733. is_fork=True,
  734. parent_id=1,
  735. hook_token='aaabbbvvv',
  736. )
  737. self.session.add(item)
  738. self.session.commit()
  739. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  740. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  741. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  742. self.assertTrue(os.path.exists(outputconf))
  743. with open(outputconf) as stream:
  744. data = stream.read()
  745. exp = """@devs = pingou
  746. @sysadmin = pingou
  747. # end of groups
  748. repo test
  749. R = @all
  750. RW+ = pingou
  751. RW+ = foo
  752. repo docs/test
  753. R = @all
  754. RW+ = pingou
  755. RW+ = foo
  756. repo tickets/test
  757. RW+ = pingou
  758. RW+ = foo
  759. repo requests/test
  760. RW+ = pingou
  761. RW+ = foo
  762. repo test2
  763. R = @all
  764. RW+ = pingou
  765. repo docs/test2
  766. R = @all
  767. RW+ = pingou
  768. repo tickets/test2
  769. RW+ = pingou
  770. repo requests/test2
  771. RW+ = pingou
  772. repo somenamespace/test3
  773. R = @all
  774. RW+ = pingou
  775. repo docs/somenamespace/test3
  776. R = @all
  777. RW+ = pingou
  778. repo tickets/somenamespace/test3
  779. RW+ = pingou
  780. repo requests/somenamespace/test3
  781. RW+ = pingou
  782. repo forks/pingou/test2
  783. R = @all
  784. RW+ = pingou
  785. repo docs/forks/pingou/test2
  786. R = @all
  787. RW+ = pingou
  788. repo tickets/forks/pingou/test2
  789. RW+ = pingou
  790. repo requests/forks/pingou/test2
  791. RW+ = pingou
  792. # end of body
  793. """
  794. #print data
  795. self.assertEqual(data.split('\n'), exp.split('\n'))
  796. os.unlink(outputconf)
  797. self.assertFalse(os.path.exists(outputconf))
  798. def test_write_gitolite_acls_groups_commit(self):
  799. """ Test the write_gitolite_acls function of pagure.lib.git with
  800. groups as committers
  801. """
  802. tests.create_projects(self.session)
  803. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  804. # Add a couple of groups
  805. # They would be committers
  806. msg = pagure.lib.query.add_group(
  807. self.session,
  808. group_name='sysadmin',
  809. display_name='sysadmin group',
  810. description=None,
  811. group_type='user',
  812. user='pingou',
  813. is_admin=False,
  814. blacklist=[],
  815. )
  816. self.session.commit()
  817. self.assertEqual(msg, 'User `pingou` added to the group `sysadmin`.')
  818. msg = pagure.lib.query.add_group(
  819. self.session,
  820. group_name='devs',
  821. display_name='devs group',
  822. description=None,
  823. group_type='user',
  824. user='pingou',
  825. is_admin=False,
  826. blacklist=[],
  827. )
  828. self.session.commit()
  829. self.assertEqual(msg, 'User `pingou` added to the group `devs`.')
  830. # Associate these groups to a project
  831. msg = pagure.lib.query.add_group_to_project(
  832. session=self.session,
  833. project=repo,
  834. new_group='sysadmin',
  835. user='pingou',
  836. access='commit'
  837. )
  838. self.session.commit()
  839. self.assertEqual(msg, 'Group added')
  840. msg = pagure.lib.query.add_group_to_project(
  841. session=self.session,
  842. project=repo,
  843. new_group='devs',
  844. user='pingou',
  845. access='commit'
  846. )
  847. self.session.commit()
  848. self.assertEqual(msg, 'Group added')
  849. # Add an user to a project
  850. msg = pagure.lib.query.add_user_to_project(
  851. session=self.session,
  852. project=repo,
  853. new_user='foo',
  854. user='pingou',
  855. )
  856. self.session.commit()
  857. self.assertEqual(msg, 'User added')
  858. # Add a forked project
  859. item = pagure.lib.model.Project(
  860. user_id=1, # pingou
  861. name='test2',
  862. description='test project #2',
  863. is_fork=True,
  864. parent_id=1,
  865. hook_token='aaabbbvvv',
  866. )
  867. self.session.add(item)
  868. self.session.commit()
  869. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  870. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  871. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  872. self.assertTrue(os.path.exists(outputconf))
  873. with open(outputconf) as stream:
  874. data = stream.read()
  875. exp = """@devs = pingou
  876. @sysadmin = pingou
  877. # end of groups
  878. repo test
  879. R = @all
  880. RW+ = @devs @sysadmin
  881. RW+ = pingou
  882. RW+ = foo
  883. repo docs/test
  884. R = @all
  885. RW+ = @devs @sysadmin
  886. RW+ = pingou
  887. RW+ = foo
  888. repo tickets/test
  889. RW+ = @devs @sysadmin
  890. RW+ = pingou
  891. RW+ = foo
  892. repo requests/test
  893. RW+ = @devs @sysadmin
  894. RW+ = pingou
  895. RW+ = foo
  896. repo test2
  897. R = @all
  898. RW+ = pingou
  899. repo docs/test2
  900. R = @all
  901. RW+ = pingou
  902. repo tickets/test2
  903. RW+ = pingou
  904. repo requests/test2
  905. RW+ = pingou
  906. repo somenamespace/test3
  907. R = @all
  908. RW+ = pingou
  909. repo docs/somenamespace/test3
  910. R = @all
  911. RW+ = pingou
  912. repo tickets/somenamespace/test3
  913. RW+ = pingou
  914. repo requests/somenamespace/test3
  915. RW+ = pingou
  916. repo forks/pingou/test2
  917. R = @all
  918. RW+ = pingou
  919. repo docs/forks/pingou/test2
  920. R = @all
  921. RW+ = pingou
  922. repo tickets/forks/pingou/test2
  923. RW+ = pingou
  924. repo requests/forks/pingou/test2
  925. RW+ = pingou
  926. # end of body
  927. """
  928. #print data
  929. self.assertEqual(data.split('\n'), exp.split('\n'))
  930. os.unlink(outputconf)
  931. self.assertFalse(os.path.exists(outputconf))
  932. def test_write_gitolite_project_pr_only(self):
  933. """ Test the write_gitolite_acls function of pagure.lib.git.
  934. when the project enforces the PR approach.
  935. """
  936. tests.create_projects(self.session)
  937. repo = pagure.lib.query._get_project(self.session, 'test')
  938. # Make the project enforce the PR workflow
  939. settings = repo.settings
  940. settings['pull_request_access_only'] = True
  941. repo.settings = settings
  942. self.session.add(repo)
  943. self.session.commit()
  944. # Add an user to a project
  945. # The user will be an admin of the project
  946. msg = pagure.lib.query.add_user_to_project(
  947. session=self.session,
  948. project=repo,
  949. new_user='foo',
  950. user='pingou',
  951. )
  952. self.session.commit()
  953. self.assertEqual(msg, 'User added')
  954. # Add a forked project
  955. item = pagure.lib.model.Project(
  956. user_id=1, # pingou
  957. name='test3',
  958. description='test project #2',
  959. is_fork=True,
  960. parent_id=1,
  961. hook_token='aaabbbvvv',
  962. )
  963. self.session.add(item)
  964. self.session.commit()
  965. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  966. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  967. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  968. self.assertTrue(os.path.exists(outputconf))
  969. with open(outputconf) as stream:
  970. data = stream.read()
  971. exp = """repo docs/test
  972. R = @all
  973. RW+ = pingou
  974. RW+ = foo
  975. repo tickets/test
  976. RW+ = pingou
  977. RW+ = foo
  978. repo requests/test
  979. RW+ = pingou
  980. RW+ = foo
  981. repo test2
  982. R = @all
  983. RW+ = pingou
  984. repo docs/test2
  985. R = @all
  986. RW+ = pingou
  987. repo tickets/test2
  988. RW+ = pingou
  989. repo requests/test2
  990. RW+ = pingou
  991. repo somenamespace/test3
  992. R = @all
  993. RW+ = pingou
  994. repo docs/somenamespace/test3
  995. R = @all
  996. RW+ = pingou
  997. repo tickets/somenamespace/test3
  998. RW+ = pingou
  999. repo requests/somenamespace/test3
  1000. RW+ = pingou
  1001. repo forks/pingou/test3
  1002. R = @all
  1003. RW+ = pingou
  1004. repo docs/forks/pingou/test3
  1005. R = @all
  1006. RW+ = pingou
  1007. repo tickets/forks/pingou/test3
  1008. RW+ = pingou
  1009. repo requests/forks/pingou/test3
  1010. RW+ = pingou
  1011. # end of body
  1012. """
  1013. #print data
  1014. self.assertEqual(data, exp)
  1015. os.unlink(outputconf)
  1016. self.assertFalse(os.path.exists(outputconf))
  1017. @patch.dict('pagure.config.config', {'PR_ONLY': True})
  1018. def test_write_gitolite_global_pr_only(self):
  1019. """ Test the write_gitolite_acls function of pagure.lib.git.
  1020. when the pagure instance enforces the PR approach.
  1021. """
  1022. tests.create_projects(self.session)
  1023. repo = pagure.lib.query._get_project(self.session, 'test')
  1024. self.assertFalse(repo.settings['pull_request_access_only'])
  1025. # Add an user to a project
  1026. # The user will be an admin of the project
  1027. msg = pagure.lib.query.add_user_to_project(
  1028. session=self.session,
  1029. project=repo,
  1030. new_user='foo',
  1031. user='pingou',
  1032. )
  1033. self.session.commit()
  1034. self.assertEqual(msg, 'User added')
  1035. # Add a forked project
  1036. item = pagure.lib.model.Project(
  1037. user_id=1, # pingou
  1038. name='test3',
  1039. description='test project #2',
  1040. is_fork=True,
  1041. parent_id=1,
  1042. hook_token='aaabbbvvv',
  1043. )
  1044. self.session.add(item)
  1045. self.session.commit()
  1046. outputconf = os.path.join(self.path, 'test_gitolite.conf')
  1047. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  1048. helper.write_gitolite_acls(self.session, outputconf, project=-1)
  1049. self.assertTrue(os.path.exists(outputconf))
  1050. with open(outputconf) as stream:
  1051. data = stream.read()
  1052. exp = """repo docs/test
  1053. R = @all
  1054. RW+ = pingou
  1055. RW+ = foo
  1056. repo tickets/test
  1057. RW+ = pingou
  1058. RW+ = foo
  1059. repo requests/test
  1060. RW+ = pingou
  1061. RW+ = foo
  1062. repo docs/test2
  1063. R = @all
  1064. RW+ = pingou
  1065. repo tickets/test2
  1066. RW+ = pingou
  1067. repo requests/test2
  1068. RW+ = pingou
  1069. repo docs/somenamespace/test3
  1070. R = @all
  1071. RW+ = pingou
  1072. repo tickets/somenamespace/test3
  1073. RW+ = pingou
  1074. repo requests/somenamespace/test3
  1075. RW+ = pingou
  1076. repo forks/pingou/test3
  1077. R = @all
  1078. RW+ = pingou
  1079. repo docs/forks/pingou/test3
  1080. R = @all
  1081. RW+ = pingou
  1082. repo tickets/forks/pingou/test3
  1083. RW+ = pingou
  1084. repo requests/forks/pingou/test3
  1085. RW+ = pingou
  1086. # end of body
  1087. """
  1088. #print data
  1089. self.assertEqual(data, exp)
  1090. os.unlink(outputconf)
  1091. self.assertFalse(os.path.exists(outputconf))
  1092. @patch('pagure.lib.notify.send_email')
  1093. def test_update_git(self, email_f):
  1094. """ Test the update_git of pagure.lib.git. """
  1095. email_f.return_value = True
  1096. # Create project
  1097. item = pagure.lib.model.Project(
  1098. user_id=1, # pingou
  1099. name='test_ticket_repo',
  1100. description='test project for ticket',
  1101. hook_token='aaabbbwww',
  1102. )
  1103. self.session.add(item)
  1104. self.session.commit()
  1105. # Create repo
  1106. self.gitrepo = os.path.join(self.path, 'repos', 'tickets',
  1107. 'test_ticket_repo.git')
  1108. pygit2.init_repository(self.gitrepo, bare=True)
  1109. repo = pagure.lib.query.get_authorized_project(self.session, 'test_ticket_repo')
  1110. # Create an issue to play with
  1111. msg = pagure.lib.query.new_issue(
  1112. session=self.session,
  1113. repo=repo,
  1114. title='Test issue',
  1115. content='We should work on this',
  1116. user='pingou',
  1117. )
  1118. self.assertEqual(msg.title, 'Test issue')
  1119. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  1120. pagure.lib.git.update_git(issue, repo).get()
  1121. repo = pygit2.Repository(self.gitrepo)
  1122. commit = repo.revparse_single('HEAD')
  1123. # Use patch to validate the repo
  1124. commit_patch = pagure.lib.git.commit_to_patch(repo, commit)
  1125. exp = r"""Mon Sep 17 00:00:00 2001
  1126. From: pagure <pagure>
  1127. Subject: Updated issue <hash>: Test issue
  1128. ---
  1129. diff --git a/123 b/456
  1130. new file mode 100644
  1131. index 0000000..60f7480
  1132. --- /dev/null
  1133. +++ b/456
  1134. @@ -0,0 +1,29 @@
  1135. +{
  1136. + "assignee": null,
  1137. + "blocks": [],
  1138. + "close_status": null,
  1139. + "closed_at": null,
  1140. + "comments": [],
  1141. + "content": "We should work on this",
  1142. + "custom_fields": [],
  1143. + "date_created": null,
  1144. + "depends": [],
  1145. + "id": 1,
  1146. + "last_updated": null,
  1147. + "milestone": null,
  1148. + "priority": null,
  1149. + "private": false,
  1150. + "status": "Open",
  1151. + "tags": [],
  1152. + "title": "Test issue",
  1153. + "user": {
  1154. + "default_email": "bar@pingou.com",
  1155. + "emails": [
  1156. + "bar@pingou.com",
  1157. + "foo@pingou.com"
  1158. + ],
  1159. + "fullname": "PY C",
  1160. + "name": "pingou"
  1161. + }
  1162. +}
  1163. \ No newline at end of file
  1164. """
  1165. npatch = []
  1166. for row in commit_patch.split('\n'):
  1167. if row.startswith('Date:'):
  1168. continue
  1169. elif row.startswith('From '):
  1170. row = row.split(' ', 2)[2]
  1171. elif row.startswith('diff --git '):
  1172. row = row.split(' ')
  1173. row[2] = 'a/123'
  1174. row[3] = 'b/456'
  1175. row = ' '.join(row)
  1176. elif 'Updated issue' in row:
  1177. row = row.split()
  1178. row[3] = '<hash>:'
  1179. row = ' '.join(row)
  1180. elif 'date_created' in row:
  1181. t = row.split(': ')[0]
  1182. row = '%s: null,' % t
  1183. elif 'last_updated' in row:
  1184. t = row.split(': ')[0]
  1185. row = '%s: null,' % t
  1186. elif 'closed_at' in row:
  1187. t = row.split(': ')[0]
  1188. row = '%s: null,' % t
  1189. elif 'closed_by' in row:
  1190. continue
  1191. elif row.startswith('index 00'):
  1192. row = 'index 0000000..60f7480'
  1193. elif row.startswith('+++ b/'):
  1194. row = '+++ b/456'
  1195. npatch.append(row)
  1196. commit_patch = '\n'.join(npatch)
  1197. #print commit_patch
  1198. self.assertEqual(commit_patch, exp)
  1199. # Enforce having a different last_updated field
  1200. # This is required as the test run fine and fast with sqlite but is
  1201. # much slower with postgresql so we end-up with an updated
  1202. # last_updated in postgresql but not with sqlite
  1203. time.sleep(1)
  1204. # Test again after adding a comment
  1205. # We need to make sure we wait for worker to commit the comment
  1206. with patch('pagure.lib.git._maybe_wait', tests.definitely_wait):
  1207. msg = pagure.lib.query.add_issue_comment(
  1208. session=self.session,
  1209. issue=issue,
  1210. comment='Hey look a comment!',
  1211. user='foo',
  1212. )
  1213. self.session.commit()
  1214. self.assertEqual(msg, 'Comment added')
  1215. # Use patch to validate the repo
  1216. repo = pygit2.Repository(self.gitrepo)
  1217. commit = repo.revparse_single('HEAD')
  1218. commit_patch = pagure.lib.git.commit_to_patch(repo, commit)
  1219. exp = r"""Mon Sep 17 00:00:00 2001
  1220. From: pagure <pagure>
  1221. Subject: Updated issue <hash>: Test issue
  1222. ---
  1223. diff --git a/123 b/456
  1224. index 458821a..77674a8
  1225. --- a/123
  1226. +++ b/456
  1227. @@ -4,13 +4,32 @@
  1228. "close_status": null,
  1229. "closed_at": null,
  1230. - "comments": [],
  1231. + "comments": [
  1232. + {
  1233. + "comment": "Hey look a comment!",
  1234. + "date_created": null,
  1235. + "edited_on": null,
  1236. + "editor": null,
  1237. + "id": 1,
  1238. + "notification": false,
  1239. + "parent": null,
  1240. + "reactions": {},
  1241. + "user": {
  1242. + "default_email": "foo@bar.com",
  1243. + "emails": [
  1244. + "foo@bar.com"
  1245. + ],
  1246. + "fullname": "foo bar",
  1247. + "name": "foo"
  1248. + }
  1249. + }
  1250. + ],
  1251. "content": "We should work on this",
  1252. "custom_fields": [],
  1253. "date_created": null,
  1254. "depends": [],
  1255. "id": 1,
  1256. - "last_updated": "<date>",
  1257. + "last_updated": "<date>",
  1258. "milestone": null,
  1259. "priority": null,
  1260. "private": false,
  1261. """
  1262. npatch = []
  1263. for row in commit_patch.split('\n'):
  1264. if row.startswith('Date:'):
  1265. continue
  1266. elif row.startswith('From '):
  1267. row = row.split(' ', 2)[2]
  1268. elif row.startswith('diff --git '):
  1269. row = row.split(' ')
  1270. row[2] = 'a/123'
  1271. row[3] = 'b/456'
  1272. row = ' '.join(row)
  1273. elif 'Updated issue' in row:
  1274. row = row.split()
  1275. row[3] = '<hash>:'
  1276. row = ' '.join(row)
  1277. elif 'date_created' in row:
  1278. t = row.split(': ')[0]
  1279. row = '%s: null,' % t
  1280. elif 'closed_at' in row:
  1281. t = row.split(': ')[0]
  1282. row = '%s: null,' % t
  1283. elif 'closed_by' in row:
  1284. continue
  1285. elif row.startswith('index'):
  1286. row = 'index 458821a..77674a8'
  1287. elif row.startswith('--- a/'):
  1288. row = '--- a/123'
  1289. elif row.startswith('+++ b/'):
  1290. row = '+++ b/456'
  1291. elif 'last_updated' in row:
  1292. t = row.split(': ')[0]
  1293. row = '%s: "<date>",' % t
  1294. npatch.append(row)
  1295. commit_patch = '\n'.join(npatch)
  1296. # print commit_patch
  1297. self.assertEqual(commit_patch, exp)
  1298. def test_clean_git(self):
  1299. """ Test the clean_git method of pagure.lib.git. """
  1300. self.test_update_git()
  1301. gitpath = os.path.join(self.path, 'repos', 'tickets',
  1302. 'test_ticket_repo.git')
  1303. gitrepo = pygit2.init_repository(gitpath, bare=True)
  1304. # Get the uid of the ticket created
  1305. commit = gitrepo.revparse_single('HEAD')
  1306. patch = pagure.lib.git.commit_to_patch(gitrepo, commit)
  1307. hash_file = None
  1308. for row in patch.split('\n'):
  1309. if row.startswith('+++ b/'):
  1310. hash_file = row.split('+++ b/')[-1]
  1311. break
  1312. # The only file in git is the one of that ticket
  1313. files = [entry.name for entry in commit.tree]
  1314. self.assertEqual(files, [hash_file])
  1315. repo = pagure.lib.query.get_authorized_project(self.session, 'test_ticket_repo')
  1316. issue = pagure.lib.query.search_issues(self.session, repo, issueid=1)
  1317. pagure.lib.git.clean_git(repo, issue.repotype, issue.uid).get()
  1318. # No more files in the git repo
  1319. commit = gitrepo.revparse_single('HEAD')
  1320. files = [entry.name for entry in commit.tree]
  1321. self.assertEqual(files, [])
  1322. @patch('pagure.lib.notify.send_email')
  1323. def test_update_git_requests(self, email_f):
  1324. """ Test the update_git of pagure.lib.git for pull-requests. """
  1325. email_f.return_value = True
  1326. # Create project
  1327. item = pagure.lib.model.Project(
  1328. user_id=1, # pingou
  1329. name='test_ticket_repo',
  1330. description='test project for ticket',
  1331. hook_token='aaabbbxxx',
  1332. )
  1333. self.session.add(item)
  1334. self.session.commit()
  1335. # Create repo
  1336. self.gitrepo = os.path.join(self.path, 'repos', 'requests',
  1337. 'test_ticket_repo.git')
  1338. pygit2.init_repository(self.gitrepo, bare=True)
  1339. # Create a PR to play with
  1340. repo = pagure.lib.query.get_authorized_project(self.session, 'test_ticket_repo')
  1341. # Create an issue to play with
  1342. req = pagure.lib.query.new_pull_request(
  1343. session=self.session,
  1344. repo_from=repo,
  1345. branch_from='feature',
  1346. repo_to=repo,
  1347. branch_to='master',
  1348. title='test PR',
  1349. user='pingou',
  1350. requestuid='foobar',
  1351. requestid=None,
  1352. status='Open',
  1353. notify=True
  1354. )
  1355. self.assertEqual(req.id, 1)
  1356. self.assertEqual(req.title, 'test PR')
  1357. request = repo.requests[0]
  1358. self.assertEqual(request.title, 'test PR')
  1359. pagure.lib.git.update_git(request, request.project).get()
  1360. repo = pygit2.Repository(self.gitrepo)
  1361. commit = repo.revparse_single('HEAD')
  1362. # Use patch to validate the repo
  1363. patch = pagure.lib.git.commit_to_patch(repo, commit)
  1364. exp = r"""Mon Sep 17 00:00:00 2001
  1365. From: pagure <pagure>
  1366. Subject: Updated pull-request <hash>: test PR
  1367. ---
  1368. diff --git a/123 b/456
  1369. new file mode 100644
  1370. index 0000000..60f7480
  1371. --- /dev/null
  1372. +++ b/456
  1373. @@ -0,0 +1,146 @@
  1374. +{
  1375. + "assignee": null,
  1376. + "branch": "master",
  1377. + "branch_from": "feature",
  1378. + "cached_merge_status": "unknown",
  1379. + "closed_at": null,
  1380. + "closed_by": null,
  1381. + "comments": [],
  1382. + "commit_start": null,
  1383. + "commit_stop": null,
  1384. + "date_created": null,
  1385. + "id": 1,
  1386. + "initial_comment": null,
  1387. + "last_updated": null,
  1388. + "project": {
  1389. + "access_groups": {
  1390. + "admin": [],
  1391. + "commit": [],
  1392. + "ticket": []
  1393. + },
  1394. + "access_users": {
  1395. + "admin": [],
  1396. + "commit": [],
  1397. + "owner": [
  1398. + "pingou"
  1399. + ],
  1400. + "ticket": []
  1401. + },
  1402. + "close_status": [],
  1403. + "custom_keys": [],
  1404. + "date_created": null,
  1405. + "date_modified": null,
  1406. + "description": "test project for ticket",
  1407. + "fullname": "test_ticket_repo",
  1408. + "id": 1,
  1409. + "milestones": {},
  1410. + "name": "test_ticket_repo",
  1411. + "namespace": null,
  1412. + "parent": null,
  1413. + "priorities": {},
  1414. + "settings": {
  1415. + "Enforce_signed-off_commits_in_pull-request": false,
  1416. + "Minimum_score_to_merge_pull-request": -1,
  1417. + "Only_assignee_can_merge_pull-request": false,
  1418. + "Web-hooks": null,
  1419. + "always_merge": false,
  1420. + "disable_non_fast-forward_merges": false,
  1421. + "fedmsg_notifications": true,
  1422. + "issue_tracker": true,
  1423. + "issue_tracker_read_only": false,
  1424. + "issues_default_to_private": false,
  1425. + "mqtt_notifications": true,
  1426. + "notify_on_commit_flag": false,
  1427. + "notify_on_pull-request_flag": false,
  1428. + "open_metadata_access_to_all": false,
  1429. + "project_documentation": false,
  1430. + "pull_request_access_only": false,
  1431. + "pull_requests": true,
  1432. + "stomp_notifications": true
  1433. + },
  1434. + "tags": [],
  1435. + "url_path": "test_ticket_repo",
  1436. + "user": {
  1437. + "default_email": "bar@pingou.com",
  1438. + "emails": [
  1439. + "bar@pingou.com",
  1440. + "foo@pingou.com"
  1441. + ],
  1442. + "fullname": "PY C",
  1443. + "name": "pingou"
  1444. + }
  1445. + },
  1446. + "remote_git": null,
  1447. + "repo_from": {
  1448. + "access_groups": {
  1449. + "admin": [],
  1450. + "commit": [],
  1451. + "ticket": []
  1452. + },
  1453. + "access_users": {
  1454. + "admin": [],
  1455. + "commit": [],
  1456. + "owner": [
  1457. + "pingou"
  1458. + ],
  1459. + "ticket": []
  1460. + },
  1461. + "close_status": [],
  1462. + "custom_keys": [],
  1463. + "date_created": null,
  1464. + "date_modified": null,
  1465. + "description": "test project for ticket",
  1466. + "fullname": "test_ticket_repo",
  1467. + "id": 1,
  1468. + "milestones": {},
  1469. + "name": "test_ticket_repo",
  1470. + "namespace": null,
  1471. + "parent": null,
  1472. + "priorities": {},
  1473. + "settings": {
  1474. + "Enforce_signed-off_commits_in_pull-request": false,
  1475. + "Minimum_score_to_merge_pull-request": -1,
  1476. + "Only_assignee_can_merge_pull-request": false,
  1477. + "Web-hooks": null,
  1478. + "always_merge": false,
  1479. + "disable_non_fast-forward_merges": false,
  1480. + "fedmsg_notifications": true,
  1481. + "issue_tracker": true,
  1482. + "issue_tracker_read_only": false,
  1483. + "issues_default_to_private": false,
  1484. + "mqtt_notifications": true,
  1485. + "notify_on_commit_flag": false,
  1486. + "notify_on_pull-request_flag": false,
  1487. + "open_metadata_access_to_all": false,
  1488. + "project_documentation": false,
  1489. + "pull_request_access_only": false,
  1490. + "pull_requests": true,
  1491. + "stomp_notifications": true
  1492. + },
  1493. + "tags": [],
  1494. + "url_path": "test_ticket_repo",
  1495. + "user": {
  1496. + "default_email": "bar@pingou.com",
  1497. + "emails": [
  1498. + "bar@pingou.com",
  1499. + "foo@pingou.com"
  1500. + ],
  1501. + "fullname": "PY C",
  1502. + "name": "pingou"
  1503. + }
  1504. + },
  1505. + "status": "Open",
  1506. + "threshold_reached": null,
  1507. + "title": "test PR",
  1508. + "uid": "foobar",
  1509. + "updated_on": null,
  1510. + "user": {
  1511. + "default_email": "bar@pingou.com",
  1512. + "emails": [
  1513. + "bar@pingou.com",
  1514. + "foo@pingou.com"
  1515. + ],
  1516. + "fullname": "PY C",
  1517. + "name": "pingou"
  1518. + }
  1519. +}
  1520. \ No newline at end of file
  1521. """
  1522. npatch = []
  1523. for row in patch.split('\n'):
  1524. if row.startswith('Date:'):
  1525. continue
  1526. elif row.startswith('From '):
  1527. row = row.split(' ', 2)[2]
  1528. elif row.startswith('diff --git '):
  1529. row = row.split(' ')
  1530. row[2] = 'a/123'
  1531. row[3] = 'b/456'
  1532. row = ' '.join(row)
  1533. elif 'Updated pull-request' in row:
  1534. row = row.split()
  1535. row[3] = '<hash>:'
  1536. row = ' '.join(row)
  1537. elif 'date_created' in row:
  1538. t = row.split(': ')[0]
  1539. row = '%s: null,' % t
  1540. elif 'date_modified' in row:
  1541. t = row.split(': ')[0]
  1542. row = '%s: null,' % t
  1543. elif 'last_updated' in row:
  1544. t = row.split(': ')[0]
  1545. row = '%s: null,' % t
  1546. elif 'updated_on' in row:
  1547. t = row.split(': ')[0]
  1548. row = '%s: null,' % t
  1549. elif row.startswith('index 00'):
  1550. row = 'index 0000000..60f7480'
  1551. elif row.startswith('+++ b/'):
  1552. row = '+++ b/456'
  1553. npatch.append(row)
  1554. patch = '\n'.join(npatch)
  1555. print(patch)
  1556. self.assertEqual(patch, exp)
  1557. def test_update_ticket_from_git_no_priority(self):
  1558. """ Test the update_ticket_from_git method from pagure.lib.git. """
  1559. tests.create_projects(self.session)
  1560. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1561. # Before
  1562. self.assertEqual(len(repo.issues), 0)
  1563. self.assertEqual(repo.issues, [])
  1564. data = {
  1565. "status": "Open", "title": "foo", "comments": [],
  1566. "content": "bar", "date_created": "1426500263",
  1567. "user": {
  1568. "name": "pingou", "emails": ["pingou@fedoraproject.org"]},
  1569. "milestone": "Next Release",
  1570. "priority": 1,
  1571. }
  1572. # Invalid project
  1573. self.assertRaises(
  1574. pagure.exceptions.PagureException,
  1575. pagure.lib.git.update_ticket_from_git,
  1576. self.session,
  1577. reponame='foobar',
  1578. namespace=None,
  1579. username=None,
  1580. issue_uid='foobar',
  1581. json_data=data,
  1582. agent='pingou',
  1583. )
  1584. # Create the issue
  1585. data = {
  1586. "status": "Open", "title": "foo", "comments": [],
  1587. "content": "bar", "date_created": "1426500263",
  1588. "user": {
  1589. "name": "pingou", "emails": ["pingou@fedoraproject.org"]},
  1590. "milestone": "Next Release",
  1591. }
  1592. pagure.lib.git.update_ticket_from_git(
  1593. self.session, reponame='test', namespace=None, username=None,
  1594. issue_uid='foobar', json_data=data, agent='pingou',
  1595. )
  1596. self.session.commit()
  1597. # Edit the issue
  1598. data = {
  1599. "status": "Open", "title": "foo", "comments": [],
  1600. "content": "bar", "date_created": "1426500263",
  1601. "user": {
  1602. "name": "pingou", "emails": ["pingou@fedoraproject.org"]},
  1603. "milestone": "Next Release",
  1604. "priority": 1,
  1605. }
  1606. pagure.lib.git.update_ticket_from_git(
  1607. self.session, reponame='test', namespace=None, username=None,
  1608. issue_uid='foobar', json_data=data, agent='pingou',
  1609. )
  1610. self.session.commit()
  1611. # Data contained a priority but not the project, so bailing
  1612. self.assertEqual(len(repo.issues), 1)
  1613. self.assertEqual(repo.issues[0].id, 1)
  1614. self.assertEqual(repo.issues[0].uid, 'foobar')
  1615. self.assertEqual(repo.issues[0].title, 'foo')
  1616. self.assertEqual(repo.issues[0].depending_text, [])
  1617. self.assertEqual(repo.issues[0].blocking_text, [])
  1618. self.assertEqual(repo.issues[0].milestone, 'Next Release')
  1619. self.assertEqual(repo.issues[0].priority, None)
  1620. self.assertEqual(
  1621. repo.milestones,
  1622. {'Next Release': {'active': True, 'date': None}})
  1623. @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
  1624. def test_update_ticket_from_git_close_ticket(self):
  1625. """ Test the update_ticket_from_git method from pagure.lib.git. """
  1626. tests.create_projects(self.session)
  1627. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1628. # Before
  1629. self.assertEqual(len(repo.issues), 0)
  1630. self.assertEqual(repo.issues, [])
  1631. # Create the issue
  1632. data = {
  1633. "status": "Open",
  1634. "title": "foo",
  1635. "comments": [],
  1636. "content": "bar",
  1637. "date_created": "1426500263",
  1638. "user": {
  1639. "name": "foo",
  1640. "emails": ["foo@fedoraproject.org"]
  1641. },
  1642. "milestone": "Next Release",
  1643. }
  1644. pagure.lib.git.update_ticket_from_git(
  1645. self.session, reponame='test', namespace=None, username=None,
  1646. issue_uid='foobar', json_data=data, agent='pingou',
  1647. )
  1648. self.session.commit()
  1649. # Edit the issue
  1650. data = {
  1651. "status": "Closed",
  1652. "close_status": "Fixed",
  1653. "title": "foo",
  1654. "comments": [],
  1655. "content": "bar",
  1656. "date_created": "1426500263",
  1657. "user": {
  1658. "name": "foo",
  1659. "emails": ["foo@fedoraproject.org"]
  1660. },
  1661. "milestone": "Next Release",
  1662. }
  1663. pagure.lib.git.update_ticket_from_git(
  1664. self.session, reponame='test', namespace=None, username=None,
  1665. issue_uid='foobar', json_data=data, agent='pingou',
  1666. )
  1667. self.session.commit()
  1668. self.assertEqual(len(repo.issues), 1)
  1669. self.assertEqual(repo.issues[0].id, 1)
  1670. self.assertEqual(repo.issues[0].uid, 'foobar')
  1671. self.assertEqual(repo.issues[0].title, 'foo')
  1672. self.assertEqual(repo.issues[0].depending_text, [])
  1673. self.assertEqual(repo.issues[0].blocking_text, [])
  1674. self.assertEqual(repo.issues[0].milestone, 'Next Release')
  1675. self.assertEqual(repo.issues[0].priority, None)
  1676. self.assertEqual(
  1677. repo.milestones,
  1678. {'Next Release': {'active': True, 'date': None}})
  1679. self.assertEqual(repo.issues[0].status, 'Closed')
  1680. self.assertEqual(repo.issues[0].close_status, 'Fixed')
  1681. self.assertIsNotNone(repo.issues[0].closed_at)
  1682. self.assertEqual(
  1683. repo.issues[0].comments[-1].comment,
  1684. '**Metadata Update from @pingou**:\n'
  1685. '- Issue close_status updated to: Fixed\n'
  1686. '- Issue status updated to: Closed (was: Open)'
  1687. )
  1688. def test_update_ticket_from_git(self):
  1689. """ Test the update_ticket_from_git method from pagure.lib.git. """
  1690. tests.create_projects(self.session)
  1691. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  1692. # Set some priorities to the project
  1693. repo.priorities = {'1': 'High', '2': 'Normal'}
  1694. self.session.add(repo)
  1695. self.session.commit()
  1696. # Before
  1697. self.assertEqual(len(repo.issues), 0)
  1698. self.assertEqual(repo.issues, [])
  1699. data = {
  1700. "status": "Open", "title": "foo", "comments": [],
  1701. "content": "bar", "date_created": "1426500263",
  1702. "user": {
  1703. "name": "pingou", "emails": ["pingou@fedoraproject.org"]},
  1704. "milestone": "Next Release",
  1705. "priority": 1,
  1706. }
  1707. self.assertRaises(
  1708. pagure.exceptions.PagureException,
  1709. pagure.lib.git.update_ticket_from_git,
  1710. self.session,
  1711. reponame='foobar',
  1712. namespace=None,
  1713. username=None,
  1714. issue_uid='foobar',
  1715. json_data=data,
  1716. agent='pingou',
  1717. )
  1718. pagure.lib.git.update_ticket_from_git(
  1719. self.session, reponame='test', namespace=None, username=None,
  1720. issue_uid='foobar', json_data=data, agent='pingou',
  1721. )
  1722. self.session.commit()
  1723. # After 1 insertion
  1724. self.assertEqual(len(repo.issues), 1)
  1725. self.assertEqual(repo.issues[0].id, 1)
  1726. self.assertEqual(repo.issues[0].uid, 'foobar')
  1727. self.assertEqual(repo.issues[0].title, 'foo')
  1728. self.assertEqual(repo.issues[0].depending_text, [])
  1729. self.assertEqual(repo.issues[0].blocking_text, [])
  1730. self.assertEqual(repo.issues[0].milestone, 'Next Release')
  1731. self.assertEqual(repo.issues[0].priority, 1)
  1732. self.assertIsNone(repo.issues[0].closed_at)
  1733. self.assertEqual(
  1734. repo.milestones,
  1735. {'Next Release': {'active': True, 'date': None}})
  1736. data["title"] = "fake issue for tests"
  1737. pagure.lib.git.update_ticket_from_git(
  1738. self.session, reponame='test', namespace=None, username=None,
  1739. issue_uid='foobar', json_data=data, agent='pingou',
  1740. )
  1741. self.session.commit()
  1742. # After edit
  1743. self.assertEqual(len(repo.issues), 1)
  1744. self.assertEqual(repo.issues[0].id, 1)
  1745. self.assertEqual(repo.issues[0].uid, 'foobar')
  1746. self.assertEqual(repo.issues[0].title, 'fake issue for tests')
  1747. self.assertEqual(repo.issues[0].depending_text, [])
  1748. self.assertEqual(repo.issues[0].blocking_text, [])
  1749. self.assertEqual(repo.issues[0].priority, 1)
  1750. self.assertIsNone(repo.issues[0].closed_at)
  1751. data = {
  1752. "status": "Open", "title": "Rename pagure", "private": False,
  1753. "content": "This is too much of a conflict with the book",
  1754. "user": {
  1755. "fullname": "Pierre-YvesChibon",
  1756. "name": "pingou",
  1757. "default_email": "pingou@fedoraproject.org",
  1758. "emails": ["pingou@fedoraproject.org"]
  1759. },
  1760. "id": 20,
  1761. "blocks": [1],
  1762. "depends": [3, 4],
  1763. "date_created": "1426595224",
  1764. "milestone": "Future",
  1765. "priority": 1,
  1766. "comments": [
  1767. {
  1768. "comment": "Nirik:\r\n\r\n- sourceforge++ \r\n- "
  1769. "gitmaker\r\n- mastergit \r\n- hostomatic\r\n- "
  1770. "gitcorp\r\n- git-keiretsu \r\n- gitbuffet\r\n- "
  1771. "cogitator\r\n- cogitate\r\n\r\nrandomuser:\r\n\r\n- "
  1772. "COLLABORATRON5000\r\n- git-sm\\u00f6rg\\u00e5sbord\r\n- "
  1773. "thislittlegittywenttomarket\r\n- git-o-rama\r\n- "
  1774. "gitsundheit",
  1775. "date_created": "1426595224", "id": 250, "parent": None,
  1776. "user": {
  1777. "fullname": "Pierre-YvesChibon",
  1778. "name": "pingou",
  1779. "default_email": "pingou@fedoraproject.org",
  1780. "emails": ["pingou@fedoraproject.org"]
  1781. }
  1782. },
  1783. {
  1784. "comment": "Nirik:\r\n\r\n- sourceforge++ \r\n- "
  1785. "gitmaker\r\n- mastergit \r\n- hostomatic\r\n- "
  1786. "gitcorp\r\n- git-keiretsu \r\n- gitbuffet\r\n- "
  1787. "cogitator\r\n- cogitate\r\n\r\nrandomuser:\r\n\r\n- "
  1788. "COLLABORATRON5000\r\n- git-sm\\u00f6rg\\u00e5sbord\r\n- "
  1789. "thislittlegittywenttomarket\r\n- git-o-rama\r\n- "
  1790. "gitsundheit",
  1791. "date_created": "1426595340", "id": 324, "parent": None,
  1792. "user": {
  1793. "fullname": "Ralph Bean",
  1794. "name": "ralph",
  1795. "default_email": "ralph@fedoraproject.org",
  1796. "emails": ["ralph@fedoraproject.org"]
  1797. }
  1798. }
  1799. ]
  1800. }
  1801. pagure.lib.git.update_ticket_from_git(
  1802. self.session, reponame='test', namespace=None, username=None,
  1803. issue_uid='foobar2', json_data=data, agent='pingou',
  1804. )
  1805. # After second insertion
  1806. self.assertEqual(len(repo.issues), 2)
  1807. self.assertEqual(repo.issues[0].uid, 'foobar')
  1808. self.assertEqual(repo.issues[0].title, 'fake issue for tests')
  1809. self.assertEqual(repo.issues[0].depending_text, [20])
  1810. self.assertEqual(repo.issues[0].blocking_text, [])
  1811. self.assertIsNone(repo.issues[0].closed_at)
  1812. # New one
  1813. self.assertEqual(repo.issues[1].uid, 'foobar2')
  1814. self.assertEqual(repo.issues[1].title, 'Rename pagure')
  1815. self.assertEqual(repo.issues[1].depending_text, [])
  1816. self.assertEqual(repo.issues[1].blocking_text, [1])
  1817. self.assertEqual(repo.issues[1].milestone, 'Future')
  1818. self.assertIsNone(repo.issues[1].closed_at)
  1819. self.assertDictEqual(
  1820. repo.milestones,
  1821. {
  1822. 'Future': {'active': True, 'date': None},
  1823. 'Next Release': {'active': True, 'date': None}
  1824. }
  1825. )
  1826. def test_update_request_from_git(self):
  1827. """ Test the update_request_from_git method from pagure.lib.git. """
  1828. tests.create_projects(self.session)
  1829. tests.create_projects_git(os.path.join(self.path, 'repos'))
  1830. repo = pagure.lib.query._get_project(self.session, 'test')
  1831. namespaced_repo = pagure.lib.query._get_project(self.session, 'test3', namespace='somenamespace')
  1832. # Before
  1833. self.assertEqual(len(repo.requests), 0)
  1834. self.assertEqual(repo.requests, [])
  1835. self.assertEqual(len(namespaced_repo.requests), 0)
  1836. self.assertEqual(namespaced_repo.requests, [])
  1837. data = {
  1838. "status": True,
  1839. "uid": "d4182a2ac2d541d884742d3037c26e56",
  1840. "project": {
  1841. "custom_keys": [],
  1842. "parent": None,
  1843. "settings": {
  1844. "issue_tracker": True,
  1845. "project_documentation": True,
  1846. "pull_requests": True,
  1847. },
  1848. "name": "test",
  1849. "date_created": "1426500194",
  1850. "tags": [],
  1851. "user": {
  1852. "fullname": "Pierre-YvesChibon",
  1853. "name": "pingou",
  1854. "default_email": "pingou@fedoraproject.org",
  1855. "emails": [
  1856. "pingou@fedoraproject.org"
  1857. ]
  1858. },
  1859. "id": 1,
  1860. "description": "test project"
  1861. },
  1862. "commit_stop": "eface8e13bc2a08a3fb22af9a72a8c90e36b8b89",
  1863. "user": {
  1864. "fullname": "Pierre-YvesChibon",
  1865. "name": "pingou",
  1866. "default_email": "pingou@fedoraproject.org",
  1867. "emails": ["pingou@fedoraproject.org"]
  1868. },
  1869. "id": 7,
  1870. "comments": [
  1871. {
  1872. "comment": "really?",
  1873. "user": {
  1874. "fullname": "Pierre-YvesChibon",
  1875. "name": "pingou",
  1876. "default_email": "pingou@fedoraproject.org",
  1877. "emails": ["pingou@fedoraproject.org"]
  1878. },
  1879. "parent": None,
  1880. "date_created": "1426843778",
  1881. "commit": "fa72f315373ec5f98f2b08c8ffae3645c97aaad2",
  1882. "line": 5,
  1883. "id": 1,
  1884. "filename": "test"
  1885. },
  1886. {
  1887. "comment": "Again ?",
  1888. "user": {
  1889. "fullname": "Pierre-YvesChibon",
  1890. "name": "pingou",
  1891. "default_email": "pingou@fedoraproject.org",
  1892. "emails": [
  1893. "pingou@fedoraproject.org"
  1894. ]
  1895. },
  1896. "parent": None,
  1897. "date_created": "1426866781",
  1898. "commit": "94ebaf900161394059478fd88aec30e59092a1d7",
  1899. "line": 5,
  1900. "id": 2,
  1901. "filename": "test2"
  1902. },
  1903. {
  1904. "comment": "Should be fine in fact",
  1905. "user": {
  1906. "fullname": "Pierre-YvesChibon",
  1907. "name": "pingou",
  1908. "default_email": "pingou@fedoraproject.org",
  1909. "emails": [
  1910. "pingou@fedoraproject.org"
  1911. ]
  1912. },
  1913. "parent": None,
  1914. "date_created": "1426866950",
  1915. "commit": "94ebaf900161394059478fd88aec30e59092a1d7",
  1916. "line": 5,
  1917. "id": 3,
  1918. "filename": "test2"
  1919. }
  1920. ],
  1921. "branch_from": "master",
  1922. "title": "test request",
  1923. "commit_start": "788efeaaf86bde8618f594a8181abb402e1dd904",
  1924. "repo_from": {
  1925. "parent": {
  1926. "custom_keys": [],
  1927. "parent": None,
  1928. "name": "test",
  1929. "date_created": "1426500194",
  1930. "tags": [],
  1931. "user": {
  1932. "fullname": "Pierre-YvesChibon",
  1933. "name": "pingou",
  1934. "default_email": "pingou@fedoraproject.org",
  1935. "emails": [
  1936. "pingou@fedoraproject.org"
  1937. ]
  1938. },
  1939. "settings": {
  1940. "issue_tracker": True,
  1941. "project_documentation": True,
  1942. "pull_requests": True,
  1943. },
  1944. "id": 1,
  1945. "description": "test project"
  1946. },
  1947. "settings": {
  1948. "issue_tracker": True,
  1949. "project_documentation": True,
  1950. "pull_requests": True,
  1951. },
  1952. "name": "test",
  1953. "date_created": "1426843440",
  1954. "custom_keys": [],
  1955. "tags": [],
  1956. "user": {
  1957. "fullname": "fake user",
  1958. "name": "fake",
  1959. "default_email": "fake@fedoraproject.org",
  1960. "emails": [
  1961. "fake@fedoraproject.org"
  1962. ]
  1963. },
  1964. "id": 6,
  1965. "description": "test project"
  1966. },
  1967. "branch": "master",
  1968. "date_created": "1426843732"
  1969. }
  1970. self.assertRaises(
  1971. pagure.exceptions.PagureException,
  1972. pagure.lib.git.update_request_from_git,
  1973. self.session,
  1974. reponame='foobar',
  1975. namespace=None,
  1976. username=None,
  1977. request_uid='d4182a2ac2d541d884742d3037c26e56',
  1978. json_data=data,
  1979. )
  1980. pagure.lib.git.update_request_from_git(
  1981. self.session,
  1982. reponame='test',
  1983. namespace=None,
  1984. username=None,
  1985. request_uid='d4182a2ac2d541d884742d3037c26e56',
  1986. json_data=data,
  1987. )
  1988. self.session.commit()
  1989. # After 1 st insertion
  1990. self.assertEqual(len(repo.requests), 1)
  1991. self.assertEqual(repo.requests[0].id, 7)
  1992. self.assertEqual(
  1993. repo.requests[0].uid, 'd4182a2ac2d541d884742d3037c26e56')
  1994. self.assertEqual(repo.requests[0].title, 'test request')
  1995. self.assertEqual(len(repo.requests[0].comments), 3)
  1996. data = {
  1997. "status": True,
  1998. "uid": "d4182a2ac2d541d884742d3037c26e57",
  1999. "project": {
  2000. "parent": None,
  2001. "name": "test",
  2002. "custom_keys": [],
  2003. "date_created": "1426500194",
  2004. "tags": [],
  2005. "user": {
  2006. "fullname": "Pierre-YvesChibon",
  2007. "name": "pingou",
  2008. "default_email": "pingou@fedoraproject.org",
  2009. "emails": [
  2010. "pingou@fedoraproject.org"
  2011. ]
  2012. },
  2013. "settings": {
  2014. "issue_tracker": True,
  2015. "project_documentation": True,
  2016. "pull_requests": True,
  2017. },
  2018. "id": 1,
  2019. "description": "test project"
  2020. },
  2021. "commit_stop": "eface8e13bc2a08a3fb22af9a72a8c90e36b8b89",
  2022. "user": {
  2023. "fullname": "Pierre-YvesChibon",
  2024. "name": "pingou",
  2025. "default_email": "pingou@fedoraproject.org",
  2026. "emails": ["pingou@fedoraproject.org"]
  2027. },
  2028. "id": 4,
  2029. "comments": [],
  2030. "branch_from": "master",
  2031. "title": "test request #2",
  2032. "commit_start": "788efeaaf86bde8618f594a8181abb402e1dd904",
  2033. "repo_from": {
  2034. "parent": {
  2035. "parent": None,
  2036. "name": "test",
  2037. "custom_keys": [],
  2038. "date_created": "1426500194",
  2039. "tags": [],
  2040. "user": {
  2041. "fullname": "Pierre-YvesChibon",
  2042. "name": "pingou",
  2043. "default_email": "pingou@fedoraproject.org",
  2044. "emails": [
  2045. "pingou@fedoraproject.org"
  2046. ]
  2047. },
  2048. "settings": {
  2049. "issue_tracker": True,
  2050. "project_documentation": True,
  2051. "pull_requests": True,
  2052. },
  2053. "id": 1,
  2054. "description": "test project"
  2055. },
  2056. "settings": {
  2057. "issue_tracker": True,
  2058. "project_documentation": True,
  2059. "pull_requests": True,
  2060. },
  2061. "name": "test",
  2062. "date_created": "1426843440",
  2063. "custom_keys": [],
  2064. "tags": [],
  2065. "user": {
  2066. "fullname": "fake user",
  2067. "name": "fake",
  2068. "default_email": "fake@fedoraproject.org",
  2069. "emails": [
  2070. "fake@fedoraproject.org"
  2071. ]
  2072. },
  2073. "project_docs": True,
  2074. "id": 6,
  2075. "description": "test project"
  2076. },
  2077. "branch": "master",
  2078. "date_created": "1426843745"
  2079. }
  2080. pagure.lib.git.update_request_from_git(
  2081. self.session,
  2082. reponame='test',
  2083. namespace=None,
  2084. username=None,
  2085. request_uid='d4182a2ac2d541d884742d3037c26e57',
  2086. json_data=data,
  2087. )
  2088. self.session.commit()
  2089. # After 2 nd insertion
  2090. self.assertEqual(len(repo.requests), 2)
  2091. self.assertEqual(repo.requests[0].id, 7)
  2092. self.assertEqual(
  2093. repo.requests[0].uid, 'd4182a2ac2d541d884742d3037c26e56')
  2094. self.assertEqual(repo.requests[0].title, 'test request')
  2095. self.assertEqual(len(repo.requests[0].comments), 3)
  2096. # 2 entry
  2097. self.assertEqual(repo.requests[1].id, 4)
  2098. self.assertEqual(
  2099. repo.requests[1].uid, 'd4182a2ac2d541d884742d3037c26e57')
  2100. self.assertEqual(repo.requests[1].title, 'test request #2')
  2101. self.assertEqual(len(repo.requests[1].comments), 0)
  2102. data = {
  2103. "status": True,
  2104. "uid": "d4182a2ac2d541d884742d3037c26e58",
  2105. "project": {
  2106. "parent": None,
  2107. "name": "test3",
  2108. "custom_keys": [],
  2109. "namespace": "somenamespace",
  2110. "date_created": "1426500194",
  2111. "tags": [],
  2112. "user": {
  2113. "fullname": "Pierre-YvesChibon",
  2114. "name": "pingou",
  2115. "default_email": "pingou@fedoraproject.org",
  2116. "emails": [
  2117. "pingou@fedoraproject.org"
  2118. ]
  2119. },
  2120. "settings": {
  2121. "issue_tracker": True,
  2122. "project_documentation": True,
  2123. "pull_requests": True,
  2124. },
  2125. "id": 3,
  2126. "description": "namespaced test project"
  2127. },
  2128. "commit_stop": "eface8e13bc2a08a3fb22af9a72a8c90e36b8b89",
  2129. "user": {
  2130. "fullname": "Pierre-YvesChibon",
  2131. "name": "pingou",
  2132. "default_email": "pingou@fedoraproject.org",
  2133. "emails": ["pingou@fedoraproject.org"]
  2134. },
  2135. "id": 5,
  2136. "comments": [],
  2137. "branch_from": "master",
  2138. "title": "test request to namespaced repo",
  2139. "commit_start": "788efeaaf86bde8618f594a8181abb402e1dd904",
  2140. "repo_from": {
  2141. "parent": {
  2142. "parent": None,
  2143. "name": "test",
  2144. "custom_keys": [],
  2145. "date_created": "1426500194",
  2146. "tags": [],
  2147. "user": {
  2148. "fullname": "Pierre-YvesChibon",
  2149. "name": "pingou",
  2150. "default_email": "pingou@fedoraproject.org",
  2151. "emails": [
  2152. "pingou@fedoraproject.org"
  2153. ]
  2154. },
  2155. "settings": {
  2156. "issue_tracker": True,
  2157. "project_documentation": True,
  2158. "pull_requests": True,
  2159. },
  2160. "id": 1,
  2161. "description": "test project"
  2162. },
  2163. "settings": {
  2164. "issue_tracker": True,
  2165. "project_documentation": True,
  2166. "pull_requests": True,
  2167. },
  2168. "name": "test",
  2169. "date_created": "1426843440",
  2170. "custom_keys": [],
  2171. "tags": [],
  2172. "user": {
  2173. "fullname": "fake user",
  2174. "name": "fake",
  2175. "default_email": "fake@fedoraproject.org",
  2176. "emails": [
  2177. "fake@fedoraproject.org"
  2178. ]
  2179. },
  2180. "project_docs": True,
  2181. "id": 6,
  2182. "description": "test project"
  2183. },
  2184. "branch": "master",
  2185. "date_created": "1426843745"
  2186. }
  2187. pagure.lib.git.update_request_from_git(
  2188. self.session,
  2189. reponame='test3',
  2190. namespace='somenamespace',
  2191. username=None,
  2192. request_uid='d4182a2ac2d541d884742d3037c26e58',
  2193. json_data=data,
  2194. )
  2195. self.session.commit()
  2196. self.assertEqual(len(namespaced_repo.requests), 1)
  2197. self.assertEqual(namespaced_repo.requests[0].id, 5)
  2198. self.assertEqual(
  2199. namespaced_repo.requests[0].uid,
  2200. 'd4182a2ac2d541d884742d3037c26e58'
  2201. )
  2202. self.assertEqual(
  2203. namespaced_repo.requests[0].title,
  2204. 'test request to namespaced repo'
  2205. )
  2206. def test_read_git_lines(self):
  2207. """ Test the read_git_lines method of pagure.lib.git. """
  2208. self.test_update_git()
  2209. gitrepo = os.path.join(self.path, 'repos', 'tickets', 'test_ticket_repo.git')
  2210. output = pagure.lib.git.read_git_lines(
  2211. ['log', '-1', "--pretty='%s'"], gitrepo)
  2212. self.assertEqual(len(output), 1)
  2213. self.assertTrue(
  2214. output[0].startswith("'Updated issue ")
  2215. )
  2216. self.assertTrue(
  2217. output[0].endswith(": Test issue'")
  2218. )
  2219. # Keeping the new line symbol
  2220. output = pagure.lib.git.read_git_lines(
  2221. ['log', '-1', "--pretty='%s'"], gitrepo, keepends=True)
  2222. self.assertEqual(len(output), 1)
  2223. self.assertTrue(
  2224. output[0].endswith(": Test issue'\n")
  2225. )
  2226. def test_get_revs_between(self):
  2227. """ Test the get_revs_between method of pagure.lib.git. """
  2228. self.test_update_git()
  2229. gitrepo = os.path.join(self.path, 'repos', 'tickets', 'test_ticket_repo.git')
  2230. output = pagure.lib.git.read_git_lines(
  2231. ['log', '-3', "--pretty='%H'"], gitrepo)
  2232. self.assertEqual(len(output), 2)
  2233. from_hash = output[1].replace("'", '')
  2234. # Case 1, repo BASE is null and HEAD is equal to from_hash
  2235. to_hash = '0'
  2236. output1 = pagure.lib.git.get_revs_between(
  2237. to_hash, from_hash, gitrepo, 'refs/heads/master')
  2238. self.assertEqual(output1, [from_hash])
  2239. # Case 2, get revs between two commits (to_hash, from_hash)
  2240. to_hash = output[0].replace("'", '')
  2241. output2 = pagure.lib.git.get_revs_between(
  2242. to_hash, from_hash, gitrepo, 'refs/heads/master')
  2243. self.assertEqual(output2, [to_hash])
  2244. # Case 3, get revs between two commits (from_hash, to_hash)
  2245. output3 = pagure.lib.git.get_revs_between(
  2246. from_hash, to_hash, gitrepo, 'refs/heads/master')
  2247. self.assertEqual(output3, [to_hash])
  2248. # Case 4, get revs between two commits on two different branches
  2249. newgitrepo = tempfile.mkdtemp(prefix='pagure-')
  2250. newrepo = pygit2.clone_repository(gitrepo, newgitrepo)
  2251. newrepo.create_branch('feature', newrepo.head.peel())
  2252. with open(os.path.join(newgitrepo, 'sources'), 'w') as stream:
  2253. stream.write('foo\n bar')
  2254. newrepo.index.add('sources')
  2255. newrepo.index.write()
  2256. # Commits the files added
  2257. tree = newrepo.index.write_tree()
  2258. author = pygit2.Signature(
  2259. 'Alice Author', 'alice@authors.tld')
  2260. committer = pygit2.Signature(
  2261. 'Cecil Committer', 'cecil@committers.tld')
  2262. newrepo.create_commit(
  2263. 'refs/heads/feature', # the name of the reference to update
  2264. author,
  2265. committer,
  2266. 'Add sources file for testing',
  2267. # binary string representing the tree object ID
  2268. tree,
  2269. # list of binary strings representing parents of the new commit
  2270. [to_hash]
  2271. )
  2272. branch_commit = newrepo.revparse_single('refs/heads/feature')
  2273. # Push to origin
  2274. ori_remote = newrepo.remotes[0]
  2275. PagureRepo.push(ori_remote, 'refs/heads/feature')
  2276. # Remove the clone
  2277. shutil.rmtree(newgitrepo)
  2278. output4 = pagure.lib.git.get_revs_between(
  2279. '0', branch_commit.oid.hex, gitrepo, 'refs/heads/feature')
  2280. self.assertEqual(output4, [branch_commit.oid.hex])
  2281. def test_get_author(self):
  2282. """ Test the get_author method of pagure.lib.git. """
  2283. self.test_update_git()
  2284. gitrepo = os.path.join(self.path, 'repos', 'tickets', 'test_ticket_repo.git')
  2285. output = pagure.lib.git.read_git_lines(
  2286. ['log', '-3', "--pretty='%H'"], gitrepo)
  2287. self.assertEqual(len(output), 2)
  2288. for githash in output:
  2289. githash = githash.replace("'", '')
  2290. output = pagure.lib.git.get_author(githash, gitrepo)
  2291. self.assertEqual(output, 'pagure')
  2292. def get_author_email(self):
  2293. """ Test the get_author_email method of pagure.lib.git. """
  2294. self.test_update_git()
  2295. gitrepo = os.path.join(self.path, 'tickets', 'test_ticket_repo.git')
  2296. output = pagure.lib.git.read_git_lines(
  2297. ['log', '-3', "--pretty='%H'"], gitrepo)
  2298. self.assertEqual(len(output), 2)
  2299. for githash in output:
  2300. githash = githash.replace("'", '')
  2301. output = pagure.lib.git.get_author_email(githash, gitrepo)
  2302. self.assertEqual(output, 'pagure')
  2303. def test_get_repo_name(self):
  2304. """ Test the get_repo_name method of pagure.lib.git. """
  2305. def runtest(reponame, *path):
  2306. gitrepo = os.path.join(self.path, 'repos', *path)
  2307. os.makedirs(gitrepo)
  2308. repo_name = pagure.lib.git.get_repo_name(gitrepo)
  2309. self.assertEqual(repo_name, reponame)
  2310. runtest('test_ticket_repo', 'tickets', 'test_ticket_repo.git')
  2311. runtest('test', 'test.git')
  2312. runtest('foo.test', 'foo.test.git')
  2313. def test_get_username(self):
  2314. """ Test the get_username method of pagure.lib.git. """
  2315. def runtest(username, *path):
  2316. gitrepo = os.path.join(self.path, 'repos', *path)
  2317. os.makedirs(gitrepo)
  2318. repo_username = pagure.lib.git.get_username(gitrepo)
  2319. self.assertEqual(repo_username, username)
  2320. runtest(None, 'tickets', 'test_ticket_repo.git')
  2321. runtest(None, 'test.git')
  2322. runtest(None, 'foo.test.git')
  2323. runtest('pingou', 'forks', 'pingou', 'foo.test.git')
  2324. runtest('pingou', 'forks', 'pingou', 'bar/foo.test.git')
  2325. def test_get_repo_namespace(self):
  2326. """ Test the get_repo_namespace method of pagure.lib.git. """
  2327. def runtest(namespace, *path):
  2328. gitrepo = os.path.join(self.path, 'repos', *path)
  2329. if not os.path.exists(gitrepo):
  2330. os.makedirs(gitrepo)
  2331. repo_namespace = pagure.lib.git.get_repo_namespace(gitrepo)
  2332. self.assertEqual(repo_namespace, namespace)
  2333. runtest(None, 'test_ticket_repo.git')
  2334. runtest('foo/bar/baz', 'foo', 'bar', 'baz', 'test.git')
  2335. runtest(None, 'foo.test.git')
  2336. runtest(None, 'forks', 'user', 'foo.test.git')
  2337. runtest('bar', 'forks', 'user', 'bar', 'foo.test.git')
  2338. runtest('ns/bar', 'forks', 'user', 'ns', 'bar', 'foo.test.git')
  2339. runtest('bar', 'forks', 'user', 'bar', 'foo.test.git')
  2340. def test_update_custom_fields_from_json(self):
  2341. """ Test the update_custom_fields_from_json method of lib.git """
  2342. tests.create_projects(self.session)
  2343. repo = pagure.lib.query._get_project(self.session, 'test')
  2344. # Create issues to play with
  2345. pagure.lib.query.new_issue(
  2346. session=self.session,
  2347. repo=repo,
  2348. title='Test issue',
  2349. content='We should work on this',
  2350. user='pingou',
  2351. issue_uid='someuid'
  2352. )
  2353. self.session.commit()
  2354. issue = pagure.lib.query.get_issue_by_uid(self.session, 'someuid')
  2355. # Fake json data, currently without custom_fields
  2356. # This should bring no new custom_fields to the issue
  2357. json_data = {
  2358. "status": "Open",
  2359. "title": "Test issue",
  2360. "private": False,
  2361. "content": "We should work on this",
  2362. "user": {
  2363. "fullname": "PY C",
  2364. "name": "pingou",
  2365. "default_email": "bar@pingou.com",
  2366. "emails": ["bar@pingou.com"]
  2367. },
  2368. "id": 1,
  2369. "blocks": [],
  2370. "depends": [],
  2371. "date_created": "1234567",
  2372. "comments": [],
  2373. }
  2374. pagure.lib.git.update_custom_field_from_json(
  2375. self.session, repo, issue, json_data)
  2376. updated_issue = pagure.lib.query.get_issue_by_uid(self.session, 'someuid')
  2377. self.assertEqual(updated_issue.to_json().get('custom_fields'), [])
  2378. custom_fields = [
  2379. {
  2380. "name": "custom1",
  2381. "key_type": "text",
  2382. "value": "value1",
  2383. "key_data": None,
  2384. },
  2385. {
  2386. "name": "custom2",
  2387. "key_type": "text",
  2388. "value": "value2",
  2389. "key_data": None,
  2390. }
  2391. ]
  2392. # Again, Fake the json data but, with custom_fields in it
  2393. # The updated issue should have the custom_fields as
  2394. # was in the json_data
  2395. json_data = {
  2396. "status": "Open",
  2397. "title": "Test issue",
  2398. "private": False,
  2399. "content": "We should work on this",
  2400. "user": {
  2401. "fullname": "PY C",
  2402. "name": "pingou",
  2403. "default_email": "bar@pingou.com",
  2404. "emails": ["bar@pingou.com"]
  2405. },
  2406. "id": 1,
  2407. "blocks": [],
  2408. "depends": [],
  2409. "date_created": "1234567",
  2410. "comments": [],
  2411. "custom_fields": custom_fields,
  2412. }
  2413. pagure.lib.git.update_custom_field_from_json(
  2414. self.session, repo, issue, json_data)
  2415. updated_issue = pagure.lib.query.get_issue_by_uid(self.session, 'someuid')
  2416. custom_fields_of_issue = updated_issue.to_json().get('custom_fields')
  2417. self.assertEqual(custom_fields_of_issue, custom_fields)
  2418. @patch('pagure.lib.notify.send_email')
  2419. @patch('pagure.lib.git.update_git')
  2420. def test_merge_pull_request_no_master(self, email_f, up_git):
  2421. """ Test the merge_pull_request function when there are no master
  2422. branch in the repo. """
  2423. email_f.return_value = True
  2424. up_git.return_value = True
  2425. gitfolder = os.path.join(self.path, 'repos')
  2426. docfolder = os.path.join(self.path, 'docs')
  2427. ticketfolder = os.path.join(self.path, 'tickets')
  2428. requestfolder = os.path.join(self.path, 'requests')
  2429. # Create project
  2430. item = pagure.lib.model.Project(
  2431. user_id=1, # pingou
  2432. name='test',
  2433. description='test project',
  2434. hook_token='aaabbbwww',
  2435. )
  2436. self.session.add(item)
  2437. self.session.commit()
  2438. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2439. gitrepo = os.path.join(gitfolder, repo.path)
  2440. docrepo = os.path.join(docfolder, repo.path)
  2441. ticketrepo = os.path.join(ticketfolder, repo.path)
  2442. requestrepo = os.path.join(requestfolder, repo.path)
  2443. os.makedirs(os.path.join(self.path, 'repos', 'forks', 'foo'))
  2444. self.gitrepo = os.path.join(self.path, 'repos', 'test.git')
  2445. os.makedirs(self.gitrepo)
  2446. repo_obj = pygit2.init_repository(self.gitrepo, bare=True)
  2447. # Fork the project
  2448. task = pagure.lib.query.fork_project(
  2449. session=self.session,
  2450. user='foo',
  2451. repo=repo,
  2452. )
  2453. self.session.commit()
  2454. self.assertEqual(task.get(),
  2455. {'endpoint': 'ui_ns.view_repo',
  2456. 'repo': 'test',
  2457. 'username': 'foo',
  2458. 'namespace': None})
  2459. # Create repo, with some content
  2460. self.gitrepo = os.path.join(
  2461. self.path, 'repos', 'forks', 'foo', 'test.git')
  2462. tests.add_content_git_repo(self.gitrepo, branch='feature')
  2463. fork_repo = pagure.lib.query.get_authorized_project(self.session, 'test', user='foo')
  2464. # Create a PR to play with
  2465. req = pagure.lib.query.new_pull_request(
  2466. session=self.session,
  2467. repo_from=fork_repo,
  2468. branch_from='feature',
  2469. repo_to=repo,
  2470. branch_to='master',
  2471. title='test PR',
  2472. user='pingou',
  2473. requestuid='foobar',
  2474. requestid=None,
  2475. status='Open',
  2476. notify=True
  2477. )
  2478. self.assertEqual(req.id, 1)
  2479. self.assertEqual(req.title, 'test PR')
  2480. # `master` branch not found
  2481. msg = pagure.lib.git.merge_pull_request(
  2482. self.session,
  2483. request=req,
  2484. username='pingou',
  2485. domerge=False
  2486. )
  2487. self.assertEqual(msg, 'FFORWARD')
  2488. @patch('pagure.lib.notify.send_email')
  2489. @patch('pagure.lib.git.update_git')
  2490. def test_merge_pull_request_closed(self, email_f, up_git):
  2491. """ Test the merge_pull_request function when the PR was already
  2492. closed/merged. """
  2493. email_f.return_value = True
  2494. up_git.return_value = True
  2495. gitfolder = os.path.join(self.path, 'repos')
  2496. docfolder = os.path.join(self.path, 'docs')
  2497. ticketfolder = os.path.join(self.path, 'tickets')
  2498. requestfolder = os.path.join(self.path, 'requests')
  2499. # Create project
  2500. item = pagure.lib.model.Project(
  2501. user_id=1, # pingou
  2502. name='test',
  2503. description='test project',
  2504. hook_token='aaabbbwww',
  2505. )
  2506. self.session.add(item)
  2507. self.session.commit()
  2508. repo = pagure.lib.query.get_authorized_project(self.session, 'test')
  2509. os.makedirs(os.path.join(self.path, 'repos', 'forks', 'foo'))
  2510. self.gitrepo = os.path.join(self.path, 'repos', 'test.git')
  2511. os.makedirs(self.gitrepo)
  2512. repo_obj = pygit2.init_repository(self.gitrepo, bare=True)
  2513. tests.add_content_git_repo(self.gitrepo, branch='master')
  2514. # Fork the project
  2515. task = pagure.lib.query.fork_project(
  2516. session=self.session,
  2517. user='foo',
  2518. repo=repo,
  2519. )
  2520. self.session.commit()
  2521. self.assertEqual(task.get(),
  2522. {'endpoint': 'ui_ns.view_repo',
  2523. 'repo': 'test',
  2524. 'username': 'foo',
  2525. 'namespace': None})
  2526. # Create repo, with some content
  2527. self.gitrepo = os.path.join(
  2528. self.path, 'repos', 'forks', 'foo', 'test.git')
  2529. tests.add_content_git_repo(self.gitrepo, branch='feature')
  2530. fork_repo = pagure.lib.query.get_authorized_project(self.session, 'test', user='foo')
  2531. # Create a PR to play with
  2532. req = pagure.lib.query.new_pull_request(
  2533. session=self.session,
  2534. repo_from=fork_repo,
  2535. branch_from='feature',
  2536. repo_to=repo,
  2537. branch_to='master',
  2538. title='test PR',
  2539. user='pingou',
  2540. requestuid='foobar',
  2541. requestid=None,
  2542. status='Open',
  2543. notify=True
  2544. )
  2545. self.assertEqual(req.id, 1)
  2546. self.assertEqual(req.title, 'test PR')
  2547. # Close the PR before we ask to merge it
  2548. req.status = 'Closed'
  2549. req.closed_by_id = 2 # id:2 == foo
  2550. req.closed_at = datetime.datetime(2017, 10, 20, 12, 32, 10)
  2551. self.session.add(req)
  2552. self.session.commit()
  2553. # PR already closed
  2554. six.assertRaisesRegex(
  2555. self,
  2556. pagure.exceptions.PagureException,
  2557. 'This pull-request was merged or closed by foo',
  2558. pagure.lib.git.merge_pull_request,
  2559. self.session,
  2560. request=req,
  2561. username='pingou',
  2562. domerge=False
  2563. )
  2564. @patch('subprocess.Popen')
  2565. def test_generate_gitolite_acls(self, popen):
  2566. """ Test calling generate_gitolite_acls. """
  2567. pagure.SESSION = self.session
  2568. pagure.lib.git.SESSION = self.session
  2569. pagure.config.config['GITOLITE_HOME'] = '/tmp'
  2570. proc = MagicMock()
  2571. proc.communicate.return_value = (1, 2)
  2572. proc.returncode = 0
  2573. popen.return_value = proc
  2574. helper = pagure.lib.git_auth.get_git_auth_helper('gitolite3')
  2575. helper.generate_acls(project=None)
  2576. popen.assert_called_with(
  2577. 'HOME=/tmp gitolite compile && '
  2578. 'HOME=/tmp gitolite trigger POST_COMPILE',
  2579. cwd='/tmp', shell=True, stderr=-1, stdout=-1
  2580. )
  2581. def test_is_forced_push_new_branch(self):
  2582. self.assertFalse(
  2583. pagure.lib.git.is_forced_push(
  2584. '0000000000000000000000000000000000000000',
  2585. '^0e6e0b6c931d65ee22f67205a53933d841c6eeff',
  2586. 'path/is/not/important'
  2587. )
  2588. )
  2589. @patch("pagure.utils.get_repo_path")
  2590. def test_update_pull_ref(self, get_repo_path):
  2591. fake_pr = MagicMock()
  2592. fake_pr.uid = "1234567"
  2593. fake_pr.branch_from = "master"
  2594. fake_pr.id = 6
  2595. fake_pr.user = MagicMock()
  2596. fake_pr.user.user = "pingou"
  2597. fake_pr.project = "doesnt_matter_mocked_out"
  2598. projects = tests.create_projects_git(
  2599. os.path.join(self.path, "repos"),
  2600. bare=True
  2601. )
  2602. tests.add_content_git_repo(projects[0])
  2603. tests.add_content_git_repo(projects[1])
  2604. orig = pygit2.Repository(projects[0])
  2605. fork = pygit2.Repository(projects[1])
  2606. get_repo_path.return_value = projects[0]
  2607. # make sure that creating works the first time
  2608. pagure.lib.git.update_pull_ref(fake_pr, fork)
  2609. oldhex = fork.references["refs/heads/master"].peel().hex
  2610. self.assertEqual(
  2611. orig.references["refs/pull/6/head"].peel().hex,
  2612. oldhex,
  2613. )
  2614. # make sure that updating works correctly
  2615. tests.add_content_git_repo(projects[1], append="foobar")
  2616. newhex = fork.references["refs/heads/master"].peel().hex
  2617. self.assertNotEqual(oldhex, newhex)
  2618. pagure.lib.git.update_pull_ref(fake_pr, fork)
  2619. self.assertEqual(
  2620. orig.references["refs/pull/6/head"].peel().hex,
  2621. newhex,
  2622. )
  2623. # make sure the function works fine even if there's a leftover
  2624. # ref from previous failed run of the function
  2625. with patch("pygit2.remote.RemoteCollection.delete"):
  2626. pagure.lib.git.update_pull_ref(fake_pr, fork)
  2627. self.assertIsNotNone(fork.remotes["pingou_1234567"])
  2628. tests.add_content_git_repo(projects[1], append="foobarbaz")
  2629. newesthex = fork.references["refs/heads/master"].peel().hex
  2630. self.assertNotEqual(newhex, newesthex)
  2631. pagure.lib.git.update_pull_ref(fake_pr, fork)
  2632. self.assertEqual(
  2633. orig.references["refs/pull/6/head"].peel().hex,
  2634. newesthex,
  2635. )
  2636. class PagureLibGitCommitToPatchtests(tests.Modeltests):
  2637. """ Tests for pagure.lib.git """
  2638. maxDiff = None
  2639. def setUp(self):
  2640. """ Set up the environment for the tests. """
  2641. super(PagureLibGitCommitToPatchtests, self).setUp()
  2642. # Create a git repo to play with
  2643. self.gitrepo = os.path.join(self.path, 'repos', 'test_repo.git')
  2644. os.makedirs(self.gitrepo)
  2645. repo = pygit2.init_repository(self.gitrepo)
  2646. # Create a file in that git repo
  2647. with open(os.path.join(self.gitrepo, 'sources'), 'w') as stream:
  2648. stream.write('foo\n bar')
  2649. repo.index.add('sources')
  2650. repo.index.write()
  2651. # Commits the files added
  2652. tree = repo.index.write_tree()
  2653. author = pygit2.Signature(
  2654. 'Alice Author', 'alice@authors.tld')
  2655. committer = pygit2.Signature(
  2656. 'Cecil Committer', 'cecil@committers.tld')
  2657. repo.create_commit(
  2658. 'refs/heads/master', # the name of the reference to update
  2659. author,
  2660. committer,
  2661. 'Add sources file for testing',
  2662. # binary string representing the tree object ID
  2663. tree,
  2664. # list of binary strings representing parents of the new commit
  2665. []
  2666. )
  2667. self.first_commit = repo.revparse_single('HEAD')
  2668. # Edit the sources file again
  2669. with open(os.path.join(self.gitrepo, 'sources'), 'w') as stream:
  2670. stream.write('foo\n bar\nbaz\n boose')
  2671. repo.index.add('sources')
  2672. repo.index.write()
  2673. # Commits the files added
  2674. tree = repo.index.write_tree()
  2675. author = pygit2.Signature(
  2676. 'Alice Author', 'alice@authors.tld')
  2677. committer = pygit2.Signature(
  2678. 'Cecil Committer', 'cecil@committers.tld')
  2679. repo.create_commit(
  2680. 'refs/heads/master', # the name of the reference to update
  2681. author,
  2682. committer,
  2683. 'Add baz and boose to the sources\n\n There are more objects to '
  2684. 'consider',
  2685. # binary string representing the tree object ID
  2686. tree,
  2687. # list of binary strings representing parents of the new commit
  2688. [self.first_commit.oid.hex]
  2689. )
  2690. self.second_commit = repo.revparse_single('HEAD')
  2691. def test_commit_to_patch_first_commit(self):
  2692. """ Test the commit_to_patch function of pagure.lib.git. """
  2693. repo = pygit2.init_repository(self.gitrepo)
  2694. patch = pagure.lib.git.commit_to_patch(repo, self.first_commit)
  2695. exp = r"""Mon Sep 17 00:00:00 2001
  2696. From: Alice Author <alice@authors.tld>
  2697. Subject: Add sources file for testing
  2698. ---
  2699. diff --git a/sources b/sources
  2700. new file mode 100644
  2701. index 0000000..9f44358
  2702. --- /dev/null
  2703. +++ b/sources
  2704. @@ -0,0 +1,2 @@
  2705. +foo
  2706. + bar
  2707. \ No newline at end of file
  2708. """
  2709. npatch = []
  2710. for row in patch.split('\n'):
  2711. if row.startswith('Date:'):
  2712. continue
  2713. if row.startswith('From '):
  2714. row = row.split(' ', 2)[2]
  2715. npatch.append(row)
  2716. patch = '\n'.join(npatch)
  2717. self.assertEqual(patch, exp)
  2718. def test_commit_to_patch_single_commit(self):
  2719. """ Test the commit_to_patch function of pagure.lib.git. """
  2720. repo = pygit2.init_repository(self.gitrepo)
  2721. patch = pagure.lib.git.commit_to_patch(repo, self.second_commit)
  2722. exp = r"""Mon Sep 17 00:00:00 2001
  2723. From: Alice Author <alice@authors.tld>
  2724. Subject: Add baz and boose to the sources
  2725. There are more objects to consider
  2726. ---
  2727. diff --git a/sources b/sources
  2728. index 9f44358..2a552bb 100644
  2729. --- a/sources
  2730. +++ b/sources
  2731. @@ -1,2 +1,4 @@
  2732. foo
  2733. - bar
  2734. \ No newline at end of file
  2735. + bar
  2736. +baz
  2737. + boose
  2738. \ No newline at end of file
  2739. """
  2740. npatch = []
  2741. for row in patch.split('\n'):
  2742. if row.startswith('Date:'):
  2743. continue
  2744. if row.startswith('From '):
  2745. row = row.split(' ', 2)[2]
  2746. npatch.append(row)
  2747. patch = '\n'.join(npatch)
  2748. self.assertEqual(patch, exp)
  2749. def test_commit_to_patch_2_commits(self):
  2750. """ Test the commit_to_patch function of pagure.lib.git. """
  2751. repo = pygit2.init_repository(self.gitrepo)
  2752. patch = pagure.lib.git.commit_to_patch(
  2753. repo, [self.first_commit, self.second_commit])
  2754. exp = r"""Mon Sep 17 00:00:00 2001
  2755. From: Alice Author <alice@authors.tld>
  2756. Subject: [PATCH 1/2] Add sources file for testing
  2757. ---
  2758. diff --git a/sources b/sources
  2759. new file mode 100644
  2760. index 0000000..9f44358
  2761. --- /dev/null
  2762. +++ b/sources
  2763. @@ -0,0 +1,2 @@
  2764. +foo
  2765. + bar
  2766. \ No newline at end of file
  2767. Mon Sep 17 00:00:00 2001
  2768. From: Alice Author <alice@authors.tld>
  2769. Subject: [PATCH 2/2] Add baz and boose to the sources
  2770. There are more objects to consider
  2771. ---
  2772. diff --git a/sources b/sources
  2773. index 9f44358..2a552bb 100644
  2774. --- a/sources
  2775. +++ b/sources
  2776. @@ -1,2 +1,4 @@
  2777. foo
  2778. - bar
  2779. \ No newline at end of file
  2780. + bar
  2781. +baz
  2782. + boose
  2783. \ No newline at end of file
  2784. """
  2785. npatch = []
  2786. for row in patch.split('\n'):
  2787. if row.startswith('Date:'):
  2788. continue
  2789. if row.startswith('From '):
  2790. row = row.split(' ', 2)[2]
  2791. npatch.append(row)
  2792. patch = '\n'.join(npatch)
  2793. self.assertEqual(patch, exp)
  2794. def test_commit_to_patch_first_commit_diff(self):
  2795. """ Test the commit_to_patch function of pagure.lib.git. """
  2796. repo = pygit2.init_repository(self.gitrepo)
  2797. patch = pagure.lib.git.commit_to_patch(
  2798. repo, self.first_commit, diff_view=True)
  2799. exp = r"""diff --git a/sources b/sources
  2800. new file mode 100644
  2801. index 0000000..9f44358
  2802. --- /dev/null
  2803. +++ b/sources
  2804. @@ -0,0 +1,2 @@
  2805. +foo
  2806. + bar
  2807. \ No newline at end of file
  2808. """
  2809. npatch = []
  2810. for row in patch.split('\n'):
  2811. if row.startswith('Date:'):
  2812. continue
  2813. if row.startswith('From '):
  2814. row = row.split(' ', 2)[2]
  2815. npatch.append(row)
  2816. patch = '\n'.join(npatch)
  2817. self.assertEqual(patch, exp)
  2818. def test_commit_to_patch_single_commit_diff(self):
  2819. """ Test the commit_to_patch function of pagure.lib.git. """
  2820. repo = pygit2.init_repository(self.gitrepo)
  2821. patch = pagure.lib.git.commit_to_patch(
  2822. repo, self.second_commit, diff_view=True)
  2823. exp = r"""diff --git a/sources b/sources
  2824. index 9f44358..2a552bb 100644
  2825. --- a/sources
  2826. +++ b/sources
  2827. @@ -1,2 +1,4 @@
  2828. foo
  2829. - bar
  2830. \ No newline at end of file
  2831. + bar
  2832. +baz
  2833. + boose
  2834. \ No newline at end of file
  2835. """
  2836. npatch = []
  2837. for row in patch.split('\n'):
  2838. if row.startswith('Date:'):
  2839. continue
  2840. if row.startswith('From '):
  2841. row = row.split(' ', 2)[2]
  2842. npatch.append(row)
  2843. patch = '\n'.join(npatch)
  2844. self.assertEqual(patch, exp)
  2845. def test_commit_to_patch_two_commits_diff(self):
  2846. """ Test the commit_to_patch function of pagure.lib.git. """
  2847. repo = pygit2.init_repository(self.gitrepo)
  2848. patch = pagure.lib.git.commit_to_patch(
  2849. repo, [self.first_commit, self.second_commit], diff_view=True)
  2850. exp = r"""diff --git a/sources b/sources
  2851. new file mode 100644
  2852. index 0000000..9f44358
  2853. --- /dev/null
  2854. +++ b/sources
  2855. @@ -0,0 +1,2 @@
  2856. +foo
  2857. + bar
  2858. \ No newline at end of file
  2859. diff --git a/sources b/sources
  2860. index 9f44358..2a552bb 100644
  2861. --- a/sources
  2862. +++ b/sources
  2863. @@ -1,2 +1,4 @@
  2864. foo
  2865. - bar
  2866. \ No newline at end of file
  2867. + bar
  2868. +baz
  2869. + boose
  2870. \ No newline at end of file
  2871. """
  2872. npatch = []
  2873. for row in patch.split('\n'):
  2874. if row.startswith('Date:'):
  2875. continue
  2876. if row.startswith('From '):
  2877. row = row.split(' ', 2)[2]
  2878. npatch.append(row)
  2879. patch = '\n'.join(npatch)
  2880. self.assertEqual(patch, exp)
  2881. def test_commit_to_patch_first_commit_diff_separated(self):
  2882. """ Test the commit_to_patch function of pagure.lib.git. """
  2883. repo = pygit2.init_repository(self.gitrepo)
  2884. patches = pagure.lib.git.commit_to_patch(
  2885. repo, self.first_commit, diff_view=True, separated=True)
  2886. exp = r"""diff --git a/sources b/sources
  2887. new file mode 100644
  2888. index 0000000..9f44358
  2889. --- /dev/null
  2890. +++ b/sources
  2891. @@ -0,0 +1,2 @@
  2892. +foo
  2893. + bar
  2894. \ No newline at end of file
  2895. """
  2896. output = []
  2897. for patch in patches:
  2898. npatch = []
  2899. for row in patch.split('\n'):
  2900. if row.startswith('Date:'):
  2901. continue
  2902. if row.startswith('From '):
  2903. row = row.split(' ', 2)[2]
  2904. npatch.append(row)
  2905. patch = '\n'.join(npatch)
  2906. output.append(patch)
  2907. self.assertEqual(output, [exp])
  2908. def test_commit_to_patch_single_commit_diff_separated(self):
  2909. """ Test the commit_to_patch function of pagure.lib.git. """
  2910. repo = pygit2.init_repository(self.gitrepo)
  2911. patches = pagure.lib.git.commit_to_patch(
  2912. repo, self.second_commit, diff_view=True, separated=True)
  2913. exp = r"""diff --git a/sources b/sources
  2914. index 9f44358..2a552bb 100644
  2915. --- a/sources
  2916. +++ b/sources
  2917. @@ -1,2 +1,4 @@
  2918. foo
  2919. - bar
  2920. \ No newline at end of file
  2921. + bar
  2922. +baz
  2923. + boose
  2924. \ No newline at end of file
  2925. """
  2926. output = []
  2927. for patch in patches:
  2928. npatch = []
  2929. for row in patch.split('\n'):
  2930. if row.startswith('Date:'):
  2931. continue
  2932. if row.startswith('From '):
  2933. row = row.split(' ', 2)[2]
  2934. npatch.append(row)
  2935. patch = '\n'.join(npatch)
  2936. output.append(patch)
  2937. self.assertEqual(output, [exp])
  2938. def test_commit_to_patch_two_commits_diff_separated(self):
  2939. """ Test the commit_to_patch function of pagure.lib.git. """
  2940. repo = pygit2.init_repository(self.gitrepo)
  2941. patches = pagure.lib.git.commit_to_patch(
  2942. repo, [self.first_commit, self.second_commit], diff_view=True,
  2943. separated=True)
  2944. exp = [r"""diff --git a/sources b/sources
  2945. new file mode 100644
  2946. index 0000000..9f44358
  2947. --- /dev/null
  2948. +++ b/sources
  2949. @@ -0,0 +1,2 @@
  2950. +foo
  2951. + bar
  2952. \ No newline at end of file
  2953. """,
  2954. r"""diff --git a/sources b/sources
  2955. index 9f44358..2a552bb 100644
  2956. --- a/sources
  2957. +++ b/sources
  2958. @@ -1,2 +1,4 @@
  2959. foo
  2960. - bar
  2961. \ No newline at end of file
  2962. + bar
  2963. +baz
  2964. + boose
  2965. \ No newline at end of file
  2966. """]
  2967. output = []
  2968. for patch in patches:
  2969. npatch = []
  2970. for row in patch.split('\n'):
  2971. if row.startswith('Date:'):
  2972. continue
  2973. if row.startswith('From '):
  2974. row = row.split(' ', 2)[2]
  2975. npatch.append(row)
  2976. patch = '\n'.join(npatch)
  2977. output.append(patch)
  2978. self.assertEqual(output, exp)
  2979. if __name__ == '__main__':
  2980. unittest.main(verbosity=2)