Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

split

  • Loading branch information...
commit 65ec9cff581ff7eea7023c81aca4350336fcba3d 1 parent 65f1cea
Dustin J. Mitchell authored
Showing with 2,044 additions and 26 deletions.
  1. 0  { → master}/bin/buildbot
  2. 0  { → master}/buildbot/__init__.py
  3. 0  { → master}/buildbot/buildbot.png
  4. 0  { → master}/buildbot/buildrequest.py
  5. 0  { → master}/buildbot/buildslave.py
  6. 0  {buildbot/test/util → master/buildbot/changes}/__init__.py
  7. 0  { → master}/buildbot/changes/base.py
  8. 0  { → master}/buildbot/changes/bonsaipoller.py
  9. 0  { → master}/buildbot/changes/changes.py
  10. 0  { → master}/buildbot/changes/freshcvs.py
  11. 0  { → master}/buildbot/changes/hgbuildbot.py
  12. 0  { → master}/buildbot/changes/mail.py
  13. 0  { → master}/buildbot/changes/maildir.py
  14. 0  { → master}/buildbot/changes/manager.py
  15. 0  { → master}/buildbot/changes/monotone.py
  16. 0  { → master}/buildbot/changes/p4poller.py
  17. 0  { → master}/buildbot/changes/pb.py
  18. 0  { → master}/buildbot/changes/svnpoller.py
  19. 0  {buildbot/test/unit → master/buildbot/clients}/__init__.py
  20. 0  { → master}/buildbot/clients/base.py
  21. 0  { → master}/buildbot/clients/debug.glade
  22. 0  { → master}/buildbot/clients/debug.py
  23. 0  { → master}/buildbot/clients/gtkPanes.py
  24. 0  { → master}/buildbot/clients/sendchange.py
  25. 0  { → master}/buildbot/clients/tryclient.py
  26. 0  { → master}/buildbot/config.py
  27. 0  { → master}/buildbot/db/__init__.py
  28. 0  { → master}/buildbot/db/connector.py
  29. 0  { → master}/buildbot/db/dbspec.py
  30. 0  { → master}/buildbot/db/exceptions.py
  31. 0  {buildbot/test/regressions → master/buildbot/db/schema}/__init__.py
  32. 0  { → master}/buildbot/db/schema/base.py
  33. 0  { → master}/buildbot/db/schema/manager.py
  34. 0  { → master}/buildbot/db/schema/tables.sql
  35. 0  { → master}/buildbot/db/schema/v1.py
  36. 0  { → master}/buildbot/db/schema/v2.py
  37. 0  { → master}/buildbot/db/schema/v3.py
  38. 0  { → master}/buildbot/db/schema/v4.py
  39. 0  { → master}/buildbot/db/schema/v5.py
  40. 0  { → master}/buildbot/db/util.py
  41. 0  { → master}/buildbot/ec2buildslave.py
  42. 0  { → master}/buildbot/interfaces.py
  43. 0  { → master}/buildbot/locks.py
  44. 0  { → master}/buildbot/manhole.py
  45. 0  { → master}/buildbot/master.py
  46. 0  { → master}/buildbot/pbutil.py
  47. 0  {buildbot/test/fake → master/buildbot/process}/__init__.py
  48. 0  { → master}/buildbot/process/base.py
  49. 0  { → master}/buildbot/process/builder.py
  50. 0  { → master}/buildbot/process/buildstep.py
  51. 0  { → master}/buildbot/process/factory.py
  52. 0  { → master}/buildbot/process/mtrlogobserver.py
  53. 0  { → master}/buildbot/process/process_twisted.py
  54. 0  { → master}/buildbot/process/properties.py
  55. 0  { → master}/buildbot/process/subunitlogobserver.py
  56. 0  { → master}/buildbot/scheduler.py
  57. 0  {buildbot/steps → master/buildbot/schedulers}/__init__.py
  58. 0  { → master}/buildbot/schedulers/base.py
  59. 0  { → master}/buildbot/schedulers/basic.py
  60. 0  { → master}/buildbot/schedulers/filter.py
  61. 0  { → master}/buildbot/schedulers/manager.py
  62. 0  { → master}/buildbot/schedulers/timed.py
  63. 0  { → master}/buildbot/schedulers/triggerable.py
  64. 0  { → master}/buildbot/schedulers/trysched.py
  65. 0  {buildbot/status/web → master/buildbot/scripts}/__init__.py
  66. 0  { → master}/buildbot/scripts/checkconfig.py
  67. 0  { → master}/buildbot/scripts/logwatcher.py
  68. 0  { → master}/buildbot/scripts/reconfig.py
  69. 0  { → master}/buildbot/scripts/runner.py
  70. 0  { → master}/buildbot/scripts/sample.cfg
  71. 0  { → master}/buildbot/scripts/startup.py
  72. 0  { → master}/buildbot/sourcestamp.py
  73. 0  { → master}/buildbot/status/__init__.py
  74. 0  { → master}/buildbot/status/base.py
  75. 0  { → master}/buildbot/status/builder.py
  76. 0  { → master}/buildbot/status/client.py
  77. 0  { → master}/buildbot/status/html.py
  78. 0  { → master}/buildbot/status/mail.py
  79. 0  { → master}/buildbot/status/persistent_queue.py
  80. 0  { → master}/buildbot/status/progress.py
  81. 0  { → master}/buildbot/status/status_push.py
  82. 0  { → master}/buildbot/status/tinderbox.py
  83. 0  {buildbot/slave/commands → master/buildbot/status/web}/__init__.py
  84. 0  { → master}/buildbot/status/web/about.py
  85. 0  { → master}/buildbot/status/web/auth.py
  86. 0  { → master}/buildbot/status/web/authz.py
  87. 0  { → master}/buildbot/status/web/base.py
  88. 0  { → master}/buildbot/status/web/baseweb.py
  89. 0  { → master}/buildbot/status/web/build.py
  90. 0  { → master}/buildbot/status/web/builder.py
  91. 0  { → master}/buildbot/status/web/buildstatus.py
  92. 0  { → master}/buildbot/status/web/changes.py
  93. 0  { → master}/buildbot/status/web/console.py
  94. 0  { → master}/buildbot/status/web/feeds.py
  95. 0  { → master}/buildbot/status/web/files/bg_gradient.jpg
  96. 0  { → master}/buildbot/status/web/files/default.css
  97. 0  { → master}/buildbot/status/web/files/favicon.ico
  98. 0  { → master}/buildbot/status/web/files/robots.txt
  99. 0  { → master}/buildbot/status/web/grid.py
  100. 0  { → master}/buildbot/status/web/logs.py
  101. 0  { → master}/buildbot/status/web/olpb.py
  102. 0  { → master}/buildbot/status/web/root.py
  103. 0  { → master}/buildbot/status/web/slaves.py
  104. 0  { → master}/buildbot/status/web/status_json.py
  105. 0  { → master}/buildbot/status/web/step.py
  106. 0  { → master}/buildbot/status/web/templates/about.html
  107. 0  { → master}/buildbot/status/web/templates/authfail.html
  108. 0  { → master}/buildbot/status/web/templates/box_macros.html
  109. 0  { → master}/buildbot/status/web/templates/build.html
  110. 0  { → master}/buildbot/status/web/templates/build_line.html
  111. 0  { → master}/buildbot/status/web/templates/builder.html
  112. 0  { → master}/buildbot/status/web/templates/builders.html
  113. 0  { → master}/buildbot/status/web/templates/buildslave.html
  114. 0  { → master}/buildbot/status/web/templates/buildslaves.html
  115. 0  { → master}/buildbot/status/web/templates/buildstatus.html
  116. 0  { → master}/buildbot/status/web/templates/buildstep.html
  117. 0  { → master}/buildbot/status/web/templates/change.html
  118. 0  { → master}/buildbot/status/web/templates/change_macros.html
  119. 0  { → master}/buildbot/status/web/templates/change_sources.html
  120. 0  { → master}/buildbot/status/web/templates/console.html
  121. 0  { → master}/buildbot/status/web/templates/directory.html
  122. 0  { → master}/buildbot/status/web/templates/empty.html
  123. 0  { → master}/buildbot/status/web/templates/feed_atom10.xml
  124. 0  { → master}/buildbot/status/web/templates/feed_description.html
  125. 0  { → master}/buildbot/status/web/templates/feed_rss20.xml
  126. 0  { → master}/buildbot/status/web/templates/footer.html
  127. 0  { → master}/buildbot/status/web/templates/forms.html
  128. 0  { → master}/buildbot/status/web/templates/grid.html
  129. 0  { → master}/buildbot/status/web/templates/grid_macros.html
  130. 0  { → master}/buildbot/status/web/templates/grid_transposed.html
  131. 0  { → master}/buildbot/status/web/templates/jsonhelp.html
  132. 0  { → master}/buildbot/status/web/templates/layout.html
  133. 0  { → master}/buildbot/status/web/templates/logs.html
  134. 0  { → master}/buildbot/status/web/templates/onelineperbuild.html
  135. 0  { → master}/buildbot/status/web/templates/onelineperbuildonebuilder.html
  136. 0  { → master}/buildbot/status/web/templates/revmacros.html
  137. 0  { → master}/buildbot/status/web/templates/root.html
  138. 0  { → master}/buildbot/status/web/templates/waterfall.html
  139. 0  { → master}/buildbot/status/web/templates/waterfallhelp.html
  140. 0  { → master}/buildbot/status/web/waterfall.py
  141. 0  { → master}/buildbot/status/web/xmlrpc.py
  142. 0  { → master}/buildbot/status/words.py
  143. 0  {buildbot/slave → master/buildbot/steps}/__init__.py
  144. 0  { → master}/buildbot/steps/dummy.py
  145. 0  { → master}/buildbot/steps/master.py
  146. 0  { → master}/buildbot/steps/maxq.py
  147. 0  { → master}/buildbot/steps/package/__init__.py
  148. 0  { → master}/buildbot/steps/package/rpm/__init__.py
  149. 0  { → master}/buildbot/steps/package/rpm/rpmbuild.py
  150. 0  { → master}/buildbot/steps/package/rpm/rpmlint.py
  151. 0  { → master}/buildbot/steps/package/rpm/rpmspec.py
  152. 0  { → master}/buildbot/steps/python.py
  153. 0  { → master}/buildbot/steps/python_twisted.py
  154. 0  { → master}/buildbot/steps/shell.py
  155. 0  { → master}/buildbot/steps/source.py
  156. 0  { → master}/buildbot/steps/subunit.py
  157. 0  { → master}/buildbot/steps/transfer.py
  158. 0  { → master}/buildbot/steps/trigger.py
  159. 0  { → master}/buildbot/steps/vstudio.py
  160. 0  { → master}/buildbot/test/__init__.py
  161. 0  {buildbot/scripts → master/buildbot/test/fake}/__init__.py
  162. 0  { → master}/buildbot/test/fake/fakedb.py
  163. 0  { → master}/buildbot/test/fake/state.py
  164. 0  {buildbot/schedulers → master/buildbot/test/regressions}/__init__.py
  165. 0  { → master}/buildbot/test/regressions/test_change_properties.py
  166. 0  { → master}/buildbot/test/regressions/test_import_unicode_changes.py
  167. 0  { → master}/buildbot/test/regressions/test_shell_command_properties.py
  168. 0  {buildbot/process → master/buildbot/test/unit}/__init__.py
  169. 0  { → master}/buildbot/test/unit/test_db_connector.py
  170. 0  { → master}/buildbot/test/unit/test_db_dbspec.py
  171. 0  { → master}/buildbot/test/unit/test_db_schema_master.py
  172. 0  { → master}/buildbot/test/unit/test_db_util.py
  173. 0  { → master}/buildbot/test/unit/test_master_cleanshutdown.py
  174. 0  { → master}/buildbot/test/unit/test_oldpaths.py
  175. 0  { → master}/buildbot/test/unit/test_persistent_queue.py
  176. 0  { → master}/buildbot/test/unit/test_schedulers_basic_Scheduler.py
  177. 0  { → master}/buildbot/test/unit/test_schedulers_filter.py
  178. 0  { → master}/buildbot/test/unit/test_source_repourl.py
  179. 0  { → master}/buildbot/test/unit/test_status_mail_MailNotifier.py
  180. 0  { → master}/buildbot/test/unit/test_status_web_authz_Authz.py
  181. 0  { → master}/buildbot/test/unit/test_status_web_links.py
  182. 0  { → master}/buildbot/test/unit/test_util.py
  183. 0  { → master}/buildbot/test/unit/test_util_ComparableMixin.py
  184. 0  { → master}/buildbot/test/unit/test_util_collections.py
  185. 0  { → master}/buildbot/test/unit/test_util_eventual.py
  186. 0  { → master}/buildbot/test/unit/test_util_loop.py
  187. 0  {buildbot/db/schema → master/buildbot/test/util}/__init__.py
  188. 0  { → master}/buildbot/util/__init__.py
  189. 0  { → master}/buildbot/util/collections.py
  190. 0  { → master}/buildbot/util/eventual.py
  191. 0  { → master}/buildbot/util/loop.py
  192. 0  { → master}/buildbot/util/monkeypatches.py
  193. +0 −2  { → master}/setup.py
  194. +1 −0  slave/bbslave/__init__.py
  195. +7 −9 {buildbot/slave → slave/bbslave}/bot.py
  196. 0  {buildbot/clients → slave/bbslave/commands}/__init__.py
  197. +3 −4 {buildbot/slave → slave/bbslave}/commands/base.py
  198. +2 −2 {buildbot/slave → slave/bbslave}/commands/registry.py
  199. +2 −2 {buildbot/slave → slave/bbslave}/commands/transfer.py
  200. 0  {buildbot/slave → slave/bbslave}/commands/utils.py
  201. +4 −4 {buildbot/slave → slave/bbslave}/commands/vcs.py
  202. 0  {buildbot/slave → slave/bbslave}/interfaces.py
  203. +140 −0 slave/bbslave/pbutil.py
  204. 0  {buildbot/changes → slave/bbslave/scripts}/__init__.py
  205. +38 −0 slave/bbslave/scripts/checkconfig.py
  206. +101 −0 slave/bbslave/scripts/logwatcher.py
  207. +69 −0 slave/bbslave/scripts/reconfig.py
  208. +1,220 −0 slave/bbslave/scripts/runner.py
  209. +206 −0 slave/bbslave/scripts/sample.cfg
  210. +126 −0 slave/bbslave/scripts/startup.py
  211. +31 −0 slave/bbslave/test/__init__.py
  212. 0  slave/bbslave/test/unit/__init__.py
  213. +2 −2 {buildbot → slave/bbslave}/test/unit/test_slave_commands_base.py
  214. +1 −1  {buildbot → slave/bbslave}/test/unit/test_slave_commands_utils.py
  215. +22 −0 slave/bbslave/util.py
  216. +69 −0 slave/setup.py
View
0  bin/buildbot → master/bin/buildbot
File renamed without changes
View
0  buildbot/__init__.py → master/buildbot/__init__.py
File renamed without changes
View
0  buildbot/buildbot.png → master/buildbot/buildbot.png
File renamed without changes
View
0  buildbot/buildrequest.py → master/buildbot/buildrequest.py
File renamed without changes
View
0  buildbot/buildslave.py → master/buildbot/buildslave.py
File renamed without changes
View
0  buildbot/test/util/__init__.py → master/buildbot/changes/__init__.py
File renamed without changes
View
0  buildbot/changes/base.py → master/buildbot/changes/base.py
File renamed without changes
View
0  buildbot/changes/bonsaipoller.py → master/buildbot/changes/bonsaipoller.py
File renamed without changes
View
0  buildbot/changes/changes.py → master/buildbot/changes/changes.py
File renamed without changes
View
0  buildbot/changes/freshcvs.py → master/buildbot/changes/freshcvs.py
File renamed without changes
View
0  buildbot/changes/hgbuildbot.py → master/buildbot/changes/hgbuildbot.py
File renamed without changes
View
0  buildbot/changes/mail.py → master/buildbot/changes/mail.py
File renamed without changes
View
0  buildbot/changes/maildir.py → master/buildbot/changes/maildir.py
File renamed without changes
View
0  buildbot/changes/manager.py → master/buildbot/changes/manager.py
File renamed without changes
View
0  buildbot/changes/monotone.py → master/buildbot/changes/monotone.py
File renamed without changes
View
0  buildbot/changes/p4poller.py → master/buildbot/changes/p4poller.py
File renamed without changes
View
0  buildbot/changes/pb.py → master/buildbot/changes/pb.py
File renamed without changes
View
0  buildbot/changes/svnpoller.py → master/buildbot/changes/svnpoller.py
File renamed without changes
View
0  buildbot/test/unit/__init__.py → master/buildbot/clients/__init__.py
File renamed without changes
View
0  buildbot/clients/base.py → master/buildbot/clients/base.py
File renamed without changes
View
0  buildbot/clients/debug.glade → master/buildbot/clients/debug.glade
File renamed without changes
View
0  buildbot/clients/debug.py → master/buildbot/clients/debug.py
File renamed without changes
View
0  buildbot/clients/gtkPanes.py → master/buildbot/clients/gtkPanes.py
File renamed without changes
View
0  buildbot/clients/sendchange.py → master/buildbot/clients/sendchange.py
File renamed without changes
View
0  buildbot/clients/tryclient.py → master/buildbot/clients/tryclient.py
File renamed without changes
View
0  buildbot/config.py → master/buildbot/config.py
File renamed without changes
View
0  buildbot/db/__init__.py → master/buildbot/db/__init__.py
File renamed without changes
View
0  buildbot/db/connector.py → master/buildbot/db/connector.py
File renamed without changes
View
0  buildbot/db/dbspec.py → master/buildbot/db/dbspec.py
File renamed without changes
View
0  buildbot/db/exceptions.py → master/buildbot/db/exceptions.py
File renamed without changes
View
0  buildbot/test/regressions/__init__.py → master/buildbot/db/schema/__init__.py
File renamed without changes
View
0  buildbot/db/schema/base.py → master/buildbot/db/schema/base.py
File renamed without changes
View
0  buildbot/db/schema/manager.py → master/buildbot/db/schema/manager.py
File renamed without changes
View
0  buildbot/db/schema/tables.sql → master/buildbot/db/schema/tables.sql
File renamed without changes
View
0  buildbot/db/schema/v1.py → master/buildbot/db/schema/v1.py
File renamed without changes
View
0  buildbot/db/schema/v2.py → master/buildbot/db/schema/v2.py
File renamed without changes
View
0  buildbot/db/schema/v3.py → master/buildbot/db/schema/v3.py
File renamed without changes
View
0  buildbot/db/schema/v4.py → master/buildbot/db/schema/v4.py
File renamed without changes
View
0  buildbot/db/schema/v5.py → master/buildbot/db/schema/v5.py
File renamed without changes
View
0  buildbot/db/util.py → master/buildbot/db/util.py
File renamed without changes
View
0  buildbot/ec2buildslave.py → master/buildbot/ec2buildslave.py
File renamed without changes
View
0  buildbot/interfaces.py → master/buildbot/interfaces.py
File renamed without changes
View
0  buildbot/locks.py → master/buildbot/locks.py
File renamed without changes
View
0  buildbot/manhole.py → master/buildbot/manhole.py
File renamed without changes
View
0  buildbot/master.py → master/buildbot/master.py
File renamed without changes
View
0  buildbot/pbutil.py → master/buildbot/pbutil.py
File renamed without changes
View
0  buildbot/test/fake/__init__.py → master/buildbot/process/__init__.py
File renamed without changes
View
0  buildbot/process/base.py → master/buildbot/process/base.py
File renamed without changes
View
0  buildbot/process/builder.py → master/buildbot/process/builder.py
File renamed without changes
View
0  buildbot/process/buildstep.py → master/buildbot/process/buildstep.py
File renamed without changes
View
0  buildbot/process/factory.py → master/buildbot/process/factory.py
File renamed without changes
View
0  buildbot/process/mtrlogobserver.py → master/buildbot/process/mtrlogobserver.py
File renamed without changes
View
0  buildbot/process/process_twisted.py → master/buildbot/process/process_twisted.py
File renamed without changes
View
0  buildbot/process/properties.py → master/buildbot/process/properties.py
File renamed without changes
View
0  buildbot/process/subunitlogobserver.py → master/buildbot/process/subunitlogobserver.py
File renamed without changes
View
0  buildbot/scheduler.py → master/buildbot/scheduler.py
File renamed without changes
View
0  buildbot/steps/__init__.py → master/buildbot/schedulers/__init__.py
File renamed without changes
View
0  buildbot/schedulers/base.py → master/buildbot/schedulers/base.py
File renamed without changes
View
0  buildbot/schedulers/basic.py → master/buildbot/schedulers/basic.py
File renamed without changes
View
0  buildbot/schedulers/filter.py → master/buildbot/schedulers/filter.py
File renamed without changes
View
0  buildbot/schedulers/manager.py → master/buildbot/schedulers/manager.py
File renamed without changes
View
0  buildbot/schedulers/timed.py → master/buildbot/schedulers/timed.py
File renamed without changes
View
0  buildbot/schedulers/triggerable.py → master/buildbot/schedulers/triggerable.py
File renamed without changes
View
0  buildbot/schedulers/trysched.py → master/buildbot/schedulers/trysched.py
File renamed without changes
View
0  buildbot/status/web/__init__.py → master/buildbot/scripts/__init__.py
File renamed without changes
View
0  buildbot/scripts/checkconfig.py → master/buildbot/scripts/checkconfig.py
File renamed without changes
View
0  buildbot/scripts/logwatcher.py → master/buildbot/scripts/logwatcher.py
File renamed without changes
View
0  buildbot/scripts/reconfig.py → master/buildbot/scripts/reconfig.py
File renamed without changes
View
0  buildbot/scripts/runner.py → master/buildbot/scripts/runner.py
File renamed without changes
View
0  buildbot/scripts/sample.cfg → master/buildbot/scripts/sample.cfg
File renamed without changes
View
0  buildbot/scripts/startup.py → master/buildbot/scripts/startup.py
File renamed without changes
View
0  buildbot/sourcestamp.py → master/buildbot/sourcestamp.py
File renamed without changes
View
0  buildbot/status/__init__.py → master/buildbot/status/__init__.py
File renamed without changes
View
0  buildbot/status/base.py → master/buildbot/status/base.py
File renamed without changes
View
0  buildbot/status/builder.py → master/buildbot/status/builder.py
File renamed without changes
View
0  buildbot/status/client.py → master/buildbot/status/client.py
File renamed without changes
View
0  buildbot/status/html.py → master/buildbot/status/html.py
File renamed without changes
View
0  buildbot/status/mail.py → master/buildbot/status/mail.py
File renamed without changes
View
0  buildbot/status/persistent_queue.py → master/buildbot/status/persistent_queue.py
File renamed without changes
View
0  buildbot/status/progress.py → master/buildbot/status/progress.py
File renamed without changes
View
0  buildbot/status/status_push.py → master/buildbot/status/status_push.py
File renamed without changes
View
0  buildbot/status/tinderbox.py → master/buildbot/status/tinderbox.py
File renamed without changes
View
0  buildbot/slave/commands/__init__.py → master/buildbot/status/web/__init__.py
File renamed without changes
View
0  buildbot/status/web/about.py → master/buildbot/status/web/about.py
File renamed without changes
View
0  buildbot/status/web/auth.py → master/buildbot/status/web/auth.py
File renamed without changes
View
0  buildbot/status/web/authz.py → master/buildbot/status/web/authz.py
File renamed without changes
View
0  buildbot/status/web/base.py → master/buildbot/status/web/base.py
File renamed without changes
View
0  buildbot/status/web/baseweb.py → master/buildbot/status/web/baseweb.py
File renamed without changes
View
0  buildbot/status/web/build.py → master/buildbot/status/web/build.py
File renamed without changes
View
0  buildbot/status/web/builder.py → master/buildbot/status/web/builder.py
File renamed without changes
View
0  buildbot/status/web/buildstatus.py → master/buildbot/status/web/buildstatus.py
File renamed without changes
View
0  buildbot/status/web/changes.py → master/buildbot/status/web/changes.py
File renamed without changes
View
0  buildbot/status/web/console.py → master/buildbot/status/web/console.py
File renamed without changes
View
0  buildbot/status/web/feeds.py → master/buildbot/status/web/feeds.py
File renamed without changes
View
0  buildbot/status/web/files/bg_gradient.jpg → master/buildbot/status/web/files/bg_gradient.jpg
File renamed without changes
View
0  buildbot/status/web/files/default.css → master/buildbot/status/web/files/default.css
File renamed without changes
View
0  buildbot/status/web/files/favicon.ico → master/buildbot/status/web/files/favicon.ico
File renamed without changes
View
0  buildbot/status/web/files/robots.txt → master/buildbot/status/web/files/robots.txt
File renamed without changes
View
0  buildbot/status/web/grid.py → master/buildbot/status/web/grid.py
File renamed without changes
View
0  buildbot/status/web/logs.py → master/buildbot/status/web/logs.py
File renamed without changes
View
0  buildbot/status/web/olpb.py → master/buildbot/status/web/olpb.py
File renamed without changes
View
0  buildbot/status/web/root.py → master/buildbot/status/web/root.py
File renamed without changes
View
0  buildbot/status/web/slaves.py → master/buildbot/status/web/slaves.py
File renamed without changes
View
0  buildbot/status/web/status_json.py → master/buildbot/status/web/status_json.py
File renamed without changes
View
0  buildbot/status/web/step.py → master/buildbot/status/web/step.py
File renamed without changes
View
0  buildbot/status/web/templates/about.html → master/buildbot/status/web/templates/about.html
File renamed without changes
View
0  buildbot/status/web/templates/authfail.html → master/buildbot/status/web/templates/authfail.html
File renamed without changes
View
0  buildbot/status/web/templates/box_macros.html → master/buildbot/status/web/templates/box_macros.html
File renamed without changes
View
0  buildbot/status/web/templates/build.html → master/buildbot/status/web/templates/build.html
File renamed without changes
View
0  buildbot/status/web/templates/build_line.html → master/buildbot/status/web/templates/build_line.html
File renamed without changes
View
0  buildbot/status/web/templates/builder.html → master/buildbot/status/web/templates/builder.html
File renamed without changes
View
0  buildbot/status/web/templates/builders.html → master/buildbot/status/web/templates/builders.html
File renamed without changes
View
0  buildbot/status/web/templates/buildslave.html → master/buildbot/status/web/templates/buildslave.html
File renamed without changes
View
0  buildbot/status/web/templates/buildslaves.html → ...er/buildbot/status/web/templates/buildslaves.html
File renamed without changes
View
0  buildbot/status/web/templates/buildstatus.html → ...er/buildbot/status/web/templates/buildstatus.html
File renamed without changes
View
0  buildbot/status/web/templates/buildstep.html → master/buildbot/status/web/templates/buildstep.html
File renamed without changes
View
0  buildbot/status/web/templates/change.html → master/buildbot/status/web/templates/change.html
File renamed without changes
View
0  buildbot/status/web/templates/change_macros.html → .../buildbot/status/web/templates/change_macros.html
File renamed without changes
View
0  buildbot/status/web/templates/change_sources.html → ...buildbot/status/web/templates/change_sources.html
File renamed without changes
View
0  buildbot/status/web/templates/console.html → master/buildbot/status/web/templates/console.html
File renamed without changes
View
0  buildbot/status/web/templates/directory.html → master/buildbot/status/web/templates/directory.html
File renamed without changes
View
0  buildbot/status/web/templates/empty.html → master/buildbot/status/web/templates/empty.html
File renamed without changes
View
0  buildbot/status/web/templates/feed_atom10.xml → master/buildbot/status/web/templates/feed_atom10.xml
File renamed without changes
View
0  buildbot/status/web/templates/feed_description.html → ...ildbot/status/web/templates/feed_description.html
File renamed without changes
View
0  buildbot/status/web/templates/feed_rss20.xml → master/buildbot/status/web/templates/feed_rss20.xml
File renamed without changes
View
0  buildbot/status/web/templates/footer.html → master/buildbot/status/web/templates/footer.html
File renamed without changes
View
0  buildbot/status/web/templates/forms.html → master/buildbot/status/web/templates/forms.html
File renamed without changes
View
0  buildbot/status/web/templates/grid.html → master/buildbot/status/web/templates/grid.html
File renamed without changes
View
0  buildbot/status/web/templates/grid_macros.html → ...er/buildbot/status/web/templates/grid_macros.html
File renamed without changes
View
0  buildbot/status/web/templates/grid_transposed.html → ...uildbot/status/web/templates/grid_transposed.html
File renamed without changes
View
0  buildbot/status/web/templates/jsonhelp.html → master/buildbot/status/web/templates/jsonhelp.html
File renamed without changes
View
0  buildbot/status/web/templates/layout.html → master/buildbot/status/web/templates/layout.html
File renamed without changes
View
0  buildbot/status/web/templates/logs.html → master/buildbot/status/web/templates/logs.html
File renamed without changes
View
0  buildbot/status/web/templates/onelineperbuild.html → ...uildbot/status/web/templates/onelineperbuild.html
File renamed without changes
View
0  ...atus/web/templates/onelineperbuildonebuilder.html → ...atus/web/templates/onelineperbuildonebuilder.html
File renamed without changes
View
0  buildbot/status/web/templates/revmacros.html → master/buildbot/status/web/templates/revmacros.html
File renamed without changes
View
0  buildbot/status/web/templates/root.html → master/buildbot/status/web/templates/root.html
File renamed without changes
View
0  buildbot/status/web/templates/waterfall.html → master/buildbot/status/web/templates/waterfall.html
File renamed without changes
View
0  buildbot/status/web/templates/waterfallhelp.html → .../buildbot/status/web/templates/waterfallhelp.html
File renamed without changes
View
0  buildbot/status/web/waterfall.py → master/buildbot/status/web/waterfall.py
File renamed without changes
View
0  buildbot/status/web/xmlrpc.py → master/buildbot/status/web/xmlrpc.py
File renamed without changes
View
0  buildbot/status/words.py → master/buildbot/status/words.py
File renamed without changes
View
0  buildbot/slave/__init__.py → master/buildbot/steps/__init__.py
File renamed without changes
View
0  buildbot/steps/dummy.py → master/buildbot/steps/dummy.py
File renamed without changes
View
0  buildbot/steps/master.py → master/buildbot/steps/master.py
File renamed without changes
View
0  buildbot/steps/maxq.py → master/buildbot/steps/maxq.py
File renamed without changes
View
0  buildbot/steps/package/__init__.py → master/buildbot/steps/package/__init__.py
File renamed without changes
View
0  buildbot/steps/package/rpm/__init__.py → master/buildbot/steps/package/rpm/__init__.py
File renamed without changes
View
0  buildbot/steps/package/rpm/rpmbuild.py → master/buildbot/steps/package/rpm/rpmbuild.py
File renamed without changes
View
0  buildbot/steps/package/rpm/rpmlint.py → master/buildbot/steps/package/rpm/rpmlint.py
File renamed without changes
View
0  buildbot/steps/package/rpm/rpmspec.py → master/buildbot/steps/package/rpm/rpmspec.py
File renamed without changes
View
0  buildbot/steps/python.py → master/buildbot/steps/python.py
File renamed without changes
View
0  buildbot/steps/python_twisted.py → master/buildbot/steps/python_twisted.py
File renamed without changes
View
0  buildbot/steps/shell.py → master/buildbot/steps/shell.py
File renamed without changes
View
0  buildbot/steps/source.py → master/buildbot/steps/source.py
File renamed without changes
View
0  buildbot/steps/subunit.py → master/buildbot/steps/subunit.py
File renamed without changes
View
0  buildbot/steps/transfer.py → master/buildbot/steps/transfer.py
File renamed without changes
View
0  buildbot/steps/trigger.py → master/buildbot/steps/trigger.py
File renamed without changes
View
0  buildbot/steps/vstudio.py → master/buildbot/steps/vstudio.py
File renamed without changes
View
0  buildbot/test/__init__.py → master/buildbot/test/__init__.py
File renamed without changes
View
0  buildbot/scripts/__init__.py → master/buildbot/test/fake/__init__.py
File renamed without changes
View
0  buildbot/test/fake/fakedb.py → master/buildbot/test/fake/fakedb.py
File renamed without changes
View
0  buildbot/test/fake/state.py → master/buildbot/test/fake/state.py
File renamed without changes
View
0  buildbot/schedulers/__init__.py → master/buildbot/test/regressions/__init__.py
File renamed without changes
View
0  buildbot/test/regressions/test_change_properties.py → ...ildbot/test/regressions/test_change_properties.py
File renamed without changes
View
0  ...t/test/regressions/test_import_unicode_changes.py → ...t/test/regressions/test_import_unicode_changes.py
File renamed without changes
View
0  ...test/regressions/test_shell_command_properties.py → ...test/regressions/test_shell_command_properties.py
File renamed without changes
View
0  buildbot/process/__init__.py → master/buildbot/test/unit/__init__.py
File renamed without changes
View
0  buildbot/test/unit/test_db_connector.py → master/buildbot/test/unit/test_db_connector.py
File renamed without changes
View
0  buildbot/test/unit/test_db_dbspec.py → master/buildbot/test/unit/test_db_dbspec.py
File renamed without changes
View
0  buildbot/test/unit/test_db_schema_master.py → master/buildbot/test/unit/test_db_schema_master.py
File renamed without changes
View
0  buildbot/test/unit/test_db_util.py → master/buildbot/test/unit/test_db_util.py
File renamed without changes
View
0  buildbot/test/unit/test_master_cleanshutdown.py → ...r/buildbot/test/unit/test_master_cleanshutdown.py
File renamed without changes
View
0  buildbot/test/unit/test_oldpaths.py → master/buildbot/test/unit/test_oldpaths.py
File renamed without changes
View
0  buildbot/test/unit/test_persistent_queue.py → master/buildbot/test/unit/test_persistent_queue.py
File renamed without changes
View
0  ...dbot/test/unit/test_schedulers_basic_Scheduler.py → ...dbot/test/unit/test_schedulers_basic_Scheduler.py
File renamed without changes
View
0  buildbot/test/unit/test_schedulers_filter.py → master/buildbot/test/unit/test_schedulers_filter.py
File renamed without changes
View
0  buildbot/test/unit/test_source_repourl.py → master/buildbot/test/unit/test_source_repourl.py
File renamed without changes
View
0  buildbot/test/unit/test_status_mail_MailNotifier.py → ...ildbot/test/unit/test_status_mail_MailNotifier.py
File renamed without changes
View
0  buildbot/test/unit/test_status_web_authz_Authz.py → ...buildbot/test/unit/test_status_web_authz_Authz.py
File renamed without changes
View
0  buildbot/test/unit/test_status_web_links.py → master/buildbot/test/unit/test_status_web_links.py
File renamed without changes
View
0  buildbot/test/unit/test_util.py → master/buildbot/test/unit/test_util.py
File renamed without changes
View
0  buildbot/test/unit/test_util_ComparableMixin.py → ...r/buildbot/test/unit/test_util_ComparableMixin.py
File renamed without changes
View
0  buildbot/test/unit/test_util_collections.py → master/buildbot/test/unit/test_util_collections.py
File renamed without changes
View
0  buildbot/test/unit/test_util_eventual.py → master/buildbot/test/unit/test_util_eventual.py
File renamed without changes
View
0  buildbot/test/unit/test_util_loop.py → master/buildbot/test/unit/test_util_loop.py
File renamed without changes
View
0  buildbot/db/schema/__init__.py → master/buildbot/test/util/__init__.py
File renamed without changes
View
0  buildbot/util/__init__.py → master/buildbot/util/__init__.py
File renamed without changes
View
0  buildbot/util/collections.py → master/buildbot/util/collections.py
File renamed without changes
View
0  buildbot/util/eventual.py → master/buildbot/util/eventual.py
File renamed without changes
View
0  buildbot/util/loop.py → master/buildbot/util/loop.py
File renamed without changes
View
0  buildbot/util/monkeypatches.py → master/buildbot/util/monkeypatches.py
File renamed without changes
View
2  setup.py → master/setup.py
@@ -192,8 +192,6 @@ def finalize_options(self):
"buildbot.steps.package.rpm",
"buildbot.process",
"buildbot.clients",
- "buildbot.slave",
- "buildbot.slave.commands",
"buildbot.schedulers",
"buildbot.scripts",
"buildbot.db",
View
1  slave/bbslave/__init__.py
@@ -0,0 +1 @@
+version = "latest"
View
16 buildbot/slave/bot.py → slave/bbslave/bot.py
@@ -1,22 +1,20 @@
-
import os.path
import sys
-import buildbot
-
from twisted.spread import pb
from twisted.python import log
from twisted.internet import reactor, defer
from twisted.application import service, internet
from twisted.cred import credentials
-from buildbot.util import now
-from buildbot.pbutil import ReconnectingPBClientFactory
-from buildbot.slave.commands import registry
+import bbslave
+from bbslave.util import now
+from bbslave.pbutil import ReconnectingPBClientFactory
+from bbslave.commands import registry
# make sure the standard commands get registered. This import is performed
# for its side-effects.
-from buildbot.slave.commands import base, transfer, vcs
+from bbslave.commands import base, transfer, vcs
class NoCommandRunning(pb.Error):
pass
@@ -343,7 +341,7 @@ def remote_getSlaveInfo(self):
def remote_getVersion(self):
"""Send our version back to the Master"""
- return buildbot.version
+ return bbslave.version
@@ -480,7 +478,7 @@ class BuildSlave(service.MultiService):
def __init__(self, buildmaster_host, port, name, passwd, basedir,
keepalive, usePTY, keepaliveTimeout=30, umask=None,
maxdelay=300, debugOpts={}, unicode_encoding=None):
- log.msg("Creating BuildSlave -- buildbot.version: %s" % buildbot.version)
+ log.msg("Creating BuildSlave -- version: %s" % bbslave.version)
service.MultiService.__init__(self)
self.debugOpts = debugOpts.copy()
bot = self.botClass(basedir, usePTY, unicode_encoding=unicode_encoding)
View
0  buildbot/clients/__init__.py → slave/bbslave/commands/__init__.py
File renamed without changes
View
7 buildbot/slave/commands/base.py → slave/bbslave/commands/base.py
@@ -1,4 +1,3 @@
-# -*- test-case-name: buildbot.test.test_slavecommand -*-
import os, signal, types, re, traceback
from stat import ST_CTIME, ST_MTIME, ST_SIZE
@@ -9,9 +8,9 @@
from twisted.internet import reactor, defer, task
from twisted.python import log, runtime
-from buildbot.slave.interfaces import ISlaveCommand
-from buildbot.slave.commands.registry import registerSlaveCommand
-from buildbot import util
+from bbslave.interfaces import ISlaveCommand
+from bbslave.commands.registry import registerSlaveCommand
+from bbslave import util
# this used to be a CVS $-style "Revision" auto-updated keyword, but since I
# moved to Darcs as the primary repository, this is updated manually each
View
4 buildbot/slave/commands/registry.py → slave/bbslave/commands/registry.py
@@ -7,9 +7,9 @@ def registerSlaveCommand(name, factory, version):
@type name: string
@param name: name under which the slave command will be registered; used
- for L{buildbot.slave.bot.SlaveBuilder.remote_startCommand}
+ for L{bbslave.bot.SlaveBuilder.remote_startCommand}
- @type factory: L{buildbot.slave.commands.Command}
+ @type factory: L{bbslave.commands.Command}
@type version: string
@param version: version string of the factory code
"""
View
4 buildbot/slave/commands/transfer.py → slave/bbslave/commands/transfer.py
@@ -3,8 +3,8 @@
from twisted.python import log
from twisted.internet import defer
-from buildbot.slave.commands.base import Command, command_version
-from buildbot.slave.commands.registry import registerSlaveCommand
+from bbslave.commands.base import Command, command_version
+from bbslave.commands.registry import registerSlaveCommand
class SlaveFileUploadCommand(Command):
"""
View
0  buildbot/slave/commands/utils.py → slave/bbslave/commands/utils.py
File renamed without changes
View
8 buildbot/slave/commands/vcs.py → slave/bbslave/commands/vcs.py
@@ -5,10 +5,10 @@
from twisted.python import log, failure, runtime
from twisted.internet import defer
-from buildbot.slave.commands.base import Command, ShellCommand, AbandonChain, command_version, Obfuscated
-from buildbot.slave.commands.registry import registerSlaveCommand
-from buildbot.slave.commands.utils import getCommand, rmdirRecursive
-from buildbot.util import remove_userpassword
+from bbslave.commands.base import Command, ShellCommand, AbandonChain, command_version, Obfuscated
+from bbslave.commands.registry import registerSlaveCommand
+from bbslave.commands.utils import getCommand, rmdirRecursive
+from bbslave.util import remove_userpassword
class SourceBase(Command):
"""Abstract base class for Version Control System operations (checkout
View
0  buildbot/slave/interfaces.py → slave/bbslave/interfaces.py
File renamed without changes
View
140 slave/bbslave/pbutil.py
@@ -0,0 +1,140 @@
+
+"""Base classes handy for use with PB clients.
+"""
+
+from twisted.spread import pb
+
+from twisted.spread.pb import PBClientFactory
+from twisted.internet import protocol
+from twisted.python import log
+
+class NewCredPerspective(pb.Avatar):
+ def attached(self, mind):
+ return self
+ def detached(self, mind):
+ pass
+
+class ReconnectingPBClientFactory(PBClientFactory,
+ protocol.ReconnectingClientFactory):
+ """Reconnecting client factory for PB brokers.
+
+ Like PBClientFactory, but if the connection fails or is lost, the factory
+ will attempt to reconnect.
+
+ Instead of using f.getRootObject (which gives a Deferred that can only
+ be fired once), override the gotRootObject method.
+
+ Instead of using the newcred f.login (which is also one-shot), call
+ f.startLogin() with the credentials and client, and override the
+ gotPerspective method.
+
+ Instead of using the oldcred f.getPerspective (also one-shot), call
+ f.startGettingPerspective() with the same arguments, and override
+ gotPerspective.
+
+ gotRootObject and gotPerspective will be called each time the object is
+ received (once per successful connection attempt). You will probably want
+ to use obj.notifyOnDisconnect to find out when the connection is lost.
+
+ If an authorization error occurs, failedToGetPerspective() will be
+ invoked.
+
+ To use me, subclass, then hand an instance to a connector (like
+ TCPClient).
+ """
+
+ def __init__(self):
+ PBClientFactory.__init__(self)
+ self._doingLogin = False
+ self._doingGetPerspective = False
+
+ def clientConnectionFailed(self, connector, reason):
+ PBClientFactory.clientConnectionFailed(self, connector, reason)
+ # Twisted-1.3 erroneously abandons the connection on non-UserErrors.
+ # To avoid this bug, don't upcall, and implement the correct version
+ # of the method here.
+ if self.continueTrying:
+ self.connector = connector
+ self.retry()
+
+ def clientConnectionLost(self, connector, reason):
+ PBClientFactory.clientConnectionLost(self, connector, reason,
+ reconnecting=True)
+ RCF = protocol.ReconnectingClientFactory
+ RCF.clientConnectionLost(self, connector, reason)
+
+ def clientConnectionMade(self, broker):
+ self.resetDelay()
+ PBClientFactory.clientConnectionMade(self, broker)
+ if self._doingLogin:
+ self.doLogin(self._root)
+ if self._doingGetPerspective:
+ self.doGetPerspective(self._root)
+ self.gotRootObject(self._root)
+
+ # oldcred methods
+
+ def getPerspective(self, *args):
+ raise RuntimeError, "getPerspective is one-shot: use startGettingPerspective instead"
+
+ def startGettingPerspective(self, username, password, serviceName,
+ perspectiveName=None, client=None):
+ self._doingGetPerspective = True
+ if perspectiveName == None:
+ perspectiveName = username
+ self._oldcredArgs = (username, password, serviceName,
+ perspectiveName, client)
+
+ def doGetPerspective(self, root):
+ # oldcred getPerspective()
+ (username, password,
+ serviceName, perspectiveName, client) = self._oldcredArgs
+ d = self._cbAuthIdentity(root, username, password)
+ d.addCallback(self._cbGetPerspective,
+ serviceName, perspectiveName, client)
+ d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
+
+
+ # newcred methods
+
+ def login(self, *args):
+ raise RuntimeError, "login is one-shot: use startLogin instead"
+
+ def startLogin(self, credentials, client=None):
+ self._credentials = credentials
+ self._client = client
+ self._doingLogin = True
+
+ def doLogin(self, root):
+ # newcred login()
+ d = self._cbSendUsername(root, self._credentials.username,
+ self._credentials.password, self._client)
+ d.addCallbacks(self.gotPerspective, self.failedToGetPerspective)
+
+
+ # methods to override
+
+ def gotPerspective(self, perspective):
+ """The remote avatar or perspective (obtained each time this factory
+ connects) is now available."""
+ pass
+
+ def gotRootObject(self, root):
+ """The remote root object (obtained each time this factory connects)
+ is now available. This method will be called each time the connection
+ is established and the object reference is retrieved."""
+ pass
+
+ def failedToGetPerspective(self, why):
+ """The login process failed, most likely because of an authorization
+ failure (bad password), but it is also possible that we lost the new
+ connection before we managed to send our credentials.
+ """
+ log.msg("ReconnectingPBClientFactory.failedToGetPerspective")
+ if why.check(pb.PBConnectionLost):
+ log.msg("we lost the brand-new connection")
+ # retrying might help here, let clientConnectionLost decide
+ return
+ # probably authorization
+ self.stopTrying() # logging in harder won't help
+ log.err(why)
View
0  buildbot/changes/__init__.py → slave/bbslave/scripts/__init__.py
File renamed without changes
View
38 slave/bbslave/scripts/checkconfig.py
@@ -0,0 +1,38 @@
+import sys
+import os
+from shutil import copy, rmtree
+from tempfile import mkdtemp
+from os.path import isfile
+
+from buildbot import master
+
+class ConfigLoader(master.BuildMaster):
+ def __init__(self, basedir=os.getcwd(), configFileName="master.cfg"):
+ master.BuildMaster.__init__(self, basedir, configFileName)
+ configFileName = os.path.join(basedir, configFileName)
+ dir = os.getcwd()
+ # Use a temporary directory since loadConfig() creates a bunch of
+ # directories and compiles .py files
+ tempdir = mkdtemp()
+ try:
+ copy(configFileName, tempdir)
+ for entry in os.listdir("."):
+ # Any code in a subdirectory will _not_ be copied! This is a bug
+ if isfile(entry) and not entry.startswith("twistd.log"):
+ copy(entry, tempdir)
+ except:
+ raise
+
+ try:
+ os.chdir(tempdir)
+ # Add the temp directory to the library path so local modules work
+ sys.path.append(tempdir)
+ configFile = open(configFileName, "r")
+ self.loadConfig(configFile, check_synchronously_only=True)
+ except:
+ os.chdir(dir)
+ configFile.close()
+ rmtree(tempdir)
+ raise
+ os.chdir(dir)
+ rmtree(tempdir)
View
101 slave/bbslave/scripts/logwatcher.py
@@ -0,0 +1,101 @@
+
+import os
+from twisted.python.failure import Failure
+from twisted.internet import defer, reactor, protocol, error
+from twisted.protocols.basic import LineOnlyReceiver
+
+class FakeTransport:
+ disconnecting = False
+
+class BuildmasterTimeoutError(Exception):
+ pass
+class BuildslaveTimeoutError(Exception):
+ pass
+class ReconfigError(Exception):
+ pass
+class BuildSlaveDetectedError(Exception):
+ pass
+
+class TailProcess(protocol.ProcessProtocol):
+ def outReceived(self, data):
+ self.lw.dataReceived(data)
+ def errReceived(self, data):
+ print "ERR: '%s'" % (data,)
+
+
+class LogWatcher(LineOnlyReceiver):
+ POLL_INTERVAL = 0.1
+ TIMEOUT_DELAY = 10.0
+ delimiter = os.linesep
+
+ def __init__(self, logfile):
+ self.logfile = logfile
+ self.in_reconfig = False
+ self.transport = FakeTransport()
+ self.pp = TailProcess()
+ self.pp.lw = self
+ self.processtype = "buildmaster"
+ self.timer = None
+
+ def start(self):
+ # If the log file doesn't exist, create it now.
+ if not os.path.exists(self.logfile):
+ open(self.logfile, 'a').close()
+
+ # return a Deferred that fires when the reconfig process has
+ # finished. It errbacks with TimeoutError if the finish line has not
+ # been seen within 10 seconds, and with ReconfigError if the error
+ # line was seen. If the logfile could not be opened, it errbacks with
+ # an IOError.
+ self.p = reactor.spawnProcess(self.pp, "/usr/bin/tail",
+ ("tail", "-f", "-n", "0", self.logfile),
+ env=os.environ,
+ )
+ self.running = True
+ d = defer.maybeDeferred(self._start)
+ return d
+
+ def _start(self):
+ self.d = defer.Deferred()
+ self.timer = reactor.callLater(self.TIMEOUT_DELAY, self.timeout)
+ return self.d
+
+ def timeout(self):
+ self.timer = None
+ if self.processtype == "buildmaster":
+ e = BuildmasterTimeoutError()
+ else:
+ e = BuildslaveTimeoutError()
+ self.finished(Failure(e))
+
+ def finished(self, results):
+ try:
+ self.p.signalProcess("KILL")
+ except error.ProcessExitedAlready:
+ pass
+ if self.timer:
+ self.timer.cancel()
+ self.timer = None
+ self.running = False
+ self.in_reconfig = False
+ self.d.callback(results)
+
+ def lineReceived(self, line):
+ if not self.running:
+ return
+ if "Log opened." in line:
+ self.in_reconfig = True
+ if "loading configuration from" in line:
+ self.in_reconfig = True
+ if "Creating BuildSlave" in line:
+ self.processtype = "buildslave"
+
+ if self.in_reconfig:
+ print line
+
+ if "message from master: attached" in line:
+ return self.finished("buildslave")
+ if "I will keep using the previous config file" in line:
+ return self.finished(Failure(ReconfigError()))
+ if "configuration update complete" in line:
+ return self.finished("buildmaster")
View
69 slave/bbslave/scripts/reconfig.py
@@ -0,0 +1,69 @@
+
+import os, signal, platform
+from twisted.internet import reactor
+
+from buildbot.scripts.logwatcher import LogWatcher, BuildmasterTimeoutError, \
+ ReconfigError
+
+class Reconfigurator:
+ def run(self, config):
+ # Returns "Microsoft" for Vista and "Windows" for other versions
+ if platform.system() in ("Windows", "Microsoft"):
+ print "Reconfig (through SIGHUP) is not supported on Windows."
+ print "The 'buildbot debugclient' tool can trigger a reconfig"
+ print "remotely, but requires Gtk+ libraries to run."
+ return
+
+ basedir = config['basedir']
+ quiet = config['quiet']
+ os.chdir(basedir)
+ f = open("twistd.pid", "rt")
+ self.pid = int(f.read().strip())
+ if quiet:
+ os.kill(self.pid, signal.SIGHUP)
+ return
+
+ # keep reading twistd.log. Display all messages between "loading
+ # configuration from ..." and "configuration update complete" or
+ # "I will keep using the previous config file instead.", or until
+ # 10 seconds have elapsed.
+
+ self.sent_signal = False
+ lw = LogWatcher("twistd.log")
+ d = lw.start()
+ d.addCallbacks(self.success, self.failure)
+ reactor.callLater(0.2, self.sighup)
+ reactor.run()
+
+ def sighup(self):
+ if self.sent_signal:
+ return
+ print "sending SIGHUP to process %d" % self.pid
+ self.sent_signal = True
+ os.kill(self.pid, signal.SIGHUP)
+
+ def success(self, res):
+ print """
+Reconfiguration appears to have completed successfully.
+"""
+ reactor.stop()
+
+ def failure(self, why):
+ if why.check(BuildmasterTimeoutError):
+ print "Never saw reconfiguration finish."
+ elif why.check(ReconfigError):
+ print """
+Reconfiguration failed. Please inspect the master.cfg file for errors,
+correct them, then try 'buildbot reconfig' again.
+"""
+ elif why.check(IOError):
+ # we were probably unable to open the file in the first place
+ self.sighup()
+ else:
+ print "Error while following twistd.log: %s" % why
+ reactor.stop()
+
+def reconfig(config):
+ r = Reconfigurator()
+ r.run(config)
+
View
1,220 slave/bbslave/scripts/runner.py
@@ -0,0 +1,1220 @@
+# -*- test-case-name: buildbot.test.test_runner -*-
+
+# N.B.: don't import anything that might pull in a reactor yet. Some of our
+# subcommands want to load modules that need the gtk reactor.
+import os, sys, stat, re, time
+import traceback
+from twisted.python import usage, util, runtime
+
+from buildbot.interfaces import BuildbotNotRunningError
+
+# the create/start/stop commands should all be run as the same user,
+# preferably a separate 'buildbot' account.
+
+# Note that the terms 'options' and 'config' are used intechangeably here - in
+# fact, they are intercanged several times. Caveat legator.
+
+class OptionsWithOptionsFile(usage.Options):
+ # subclasses should set this to a list-of-lists in order to source the
+ # .buildbot/options file.
+ # buildbotOptions = [ [ 'optfile-name', 'option-name' ], .. ]
+ buildbotOptions = None
+
+ def __init__(self, *args):
+ # for options in self.buildbotOptions, optParameters, and the options
+ # file, change the default in optParameters *before* calling through
+ # to the parent constructor
+
+ if self.buildbotOptions:
+ optfile = loadOptionsFile()
+ for optfile_name, option_name in self.buildbotOptions:
+ for i in range(len(self.optParameters)):
+ if self.optParameters[i][0] == option_name and optfile_name in optfile:
+ self.optParameters[i][2] = optfile[optfile_name]
+ usage.Options.__init__(self, *args)
+
+def loadOptionsFile(filename="options", here=None, home=None):
+ """Find the .buildbot/FILENAME file. Crawl from the current directory up
+ towards the root, and also look in ~/.buildbot . The first directory
+ that's owned by the user and has the file we're looking for wins. Windows
+ skips the owned-by-user test.
+
+ @rtype: dict
+ @return: a dictionary of names defined in the options file. If no options
+ file was found, return an empty dict.
+ """
+
+ if here is None:
+ here = os.getcwd()
+ here = os.path.abspath(here)
+
+ if home is None:
+ if runtime.platformType == 'win32':
+ # never trust env-vars, use the proper API
+ from win32com.shell import shellcon, shell
+ appdata = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)
+ home = os.path.join(appdata, "buildbot")
+ else:
+ home = os.path.expanduser("~/.buildbot")
+
+ searchpath = []
+ toomany = 20
+ while True:
+ searchpath.append(os.path.join(here, ".buildbot"))
+ next = os.path.dirname(here)
+ if next == here:
+ break # we've hit the root
+ here = next
+ toomany -= 1 # just in case
+ if toomany == 0:
+ raise ValueError("Hey, I seem to have wandered up into the "
+ "infinite glories of the heavens. Oops.")
+ searchpath.append(home)
+
+ localDict = {}
+
+ for d in searchpath:
+ if os.path.isdir(d):
+ if runtime.platformType != 'win32':
+ if os.stat(d)[stat.ST_UID] != os.getuid():
+ print "skipping %s because you don't own it" % d
+ continue # security, skip other people's directories
+ optfile = os.path.join(d, filename)
+ if os.path.exists(optfile):
+ try:
+ f = open(optfile, "r")
+ options = f.read()
+ exec options in localDict
+ except:
+ print "error while reading %s" % optfile
+ raise
+ break
+
+ for k in localDict.keys():
+ if k.startswith("__"):
+ del localDict[k]
+ return localDict
+
+class MakerBase(OptionsWithOptionsFile):
+ optFlags = [
+ ['help', 'h', "Display this message"],
+ ["quiet", "q", "Do not emit the commands being run"],
+ ]
+
+ longdesc = """
+ Operates upon the specified <basedir> (or the current directory, if not
+ specified).
+ """
+
+ opt_h = usage.Options.opt_help
+
+ def parseArgs(self, *args):
+ if len(args) > 0:
+ self['basedir'] = args[0]
+ else:
+ # Use the current directory if no basedir was specified.
+ self['basedir'] = os.getcwd()
+ if len(args) > 1:
+ raise usage.UsageError("I wasn't expecting so many arguments")
+
+ def postOptions(self):
+ self['basedir'] = os.path.abspath(self['basedir'])
+
+makefile_sample = """# -*- makefile -*-
+
+# This is a simple makefile which lives in a buildmaster/buildslave
+# directory (next to the buildbot.tac file). It allows you to start/stop the
+# master or slave by doing 'make start' or 'make stop'.
+
+# The 'reconfig' target will tell a buildmaster to reload its config file.
+
+start:
+ twistd --no_save -y buildbot.tac
+
+stop:
+ if [ -e twistd.pid ]; \\
+ then kill `cat twistd.pid`; \\
+ else echo "Nothing to stop."; \\
+ fi
+
+reconfig:
+ if [ -e twistd.pid ]; \\
+ then kill -HUP `cat twistd.pid`; \\
+ else echo "Nothing to reconfig."; \\
+ fi
+
+log:
+ if [ -e twistd.log ]; \\
+ then tail -f twistd.log; \\
+ else echo "Nothing to tail."; \\
+ fi
+"""
+
+class Maker:
+ def __init__(self, config):
+ self.config = config
+ self.basedir = config['basedir']
+ self.force = config.get('force', False)
+ self.quiet = config['quiet']
+
+ def mkdir(self):
+ if os.path.exists(self.basedir):
+ if not self.quiet:
+ print "updating existing installation"
+ return
+ if not self.quiet: print "mkdir", self.basedir
+ os.mkdir(self.basedir)
+
+ def mkinfo(self):
+ path = os.path.join(self.basedir, "info")
+ if not os.path.exists(path):
+ if not self.quiet: print "mkdir", path
+ os.mkdir(path)
+ created = False
+ admin = os.path.join(path, "admin")
+ if not os.path.exists(admin):
+ if not self.quiet:
+ print "Creating info/admin, you need to edit it appropriately"
+ f = open(admin, "wt")
+ f.write("Your Name Here <admin@youraddress.invalid>\n")
+ f.close()
+ created = True
+ host = os.path.join(path, "host")
+ if not os.path.exists(host):
+ if not self.quiet:
+ print "Creating info/host, you need to edit it appropriately"
+ f = open(host, "wt")
+ f.write("Please put a description of this build host here\n")
+ f.close()
+ created = True
+ access_uri = os.path.join(path, "access_uri")
+ if not os.path.exists(access_uri):
+ if not self.quiet:
+ print "Not creating info/access_uri - add it if you wish"
+ if created and not self.quiet:
+ print "Please edit the files in %s appropriately." % path
+
+ def chdir(self):
+ if not self.quiet: print "chdir", self.basedir
+ os.chdir(self.basedir)
+
+ def makeTAC(self, contents, secret=False):
+ tacfile = "buildbot.tac"
+ if os.path.exists(tacfile):
+ oldcontents = open(tacfile, "rt").read()
+ if oldcontents == contents:
+ if not self.quiet:
+ print "buildbot.tac already exists and is correct"
+ return
+ if not self.quiet:
+ print "not touching existing buildbot.tac"
+ print "creating buildbot.tac.new instead"
+ tacfile = "buildbot.tac.new"
+ f = open(tacfile, "wt")
+ f.write(contents)
+ f.close()
+ if secret:
+ os.chmod(tacfile, 0600)
+
+ def makefile(self):
+ target = "Makefile.sample"
+ if os.path.exists(target):
+ oldcontents = open(target, "rt").read()
+ if oldcontents == makefile_sample:
+ if not self.quiet:
+ print "Makefile.sample already exists and is correct"
+ return
+ if not self.quiet:
+ print "replacing Makefile.sample"
+ else:
+ if not self.quiet:
+ print "creating Makefile.sample"
+ f = open(target, "wt")
+ f.write(makefile_sample)
+ f.close()
+
+ def sampleconfig(self, source):
+ target = "master.cfg.sample"
+ config_sample = open(source, "rt").read()
+ if os.path.exists(target):
+ oldcontents = open(target, "rt").read()
+ if oldcontents == config_sample:
+ if not self.quiet:
+ print "master.cfg.sample already exists and is up-to-date"
+ return
+ if not self.quiet:
+ print "replacing master.cfg.sample"
+ else:
+ if not self.quiet:
+ print "creating master.cfg.sample"
+ f = open(target, "wt")
+ f.write(config_sample)
+ f.close()
+ os.chmod(target, 0600)
+
+ def public_html(self, files):
+ webdir = os.path.join(self.basedir, "public_html")
+ if os.path.exists(webdir):
+ if not self.quiet:
+ print "public_html/ already exists: not replacing"
+ return
+ else:
+ os.mkdir(webdir)
+ if not self.quiet:
+ print "populating public_html/"
+ for target, source in files.iteritems():
+ target = os.path.join(webdir, target)
+ f = open(target, "wt")
+ f.write(open(source, "rt").read())
+ f.close()
+
+ def create_db(self):
+ from buildbot.db import dbspec, exceptions, schema
+ spec = dbspec.DBSpec.from_url(self.config["db"], self.basedir)
+ if not self.config['quiet']: print "creating database"
+
+ # upgrade from "nothing"
+ sm = schema.DBSchemaManager(spec, self.basedir)
+ if sm.get_db_version() != 0:
+ raise exceptions.DBAlreadyExistsError
+ sm.upgrade()
+
+ def populate_if_missing(self, target, source, overwrite=False):
+ new_contents = open(source, "rt").read()
+ if os.path.exists(target):
+ old_contents = open(target, "rt").read()
+ if old_contents != new_contents:
+ if overwrite:
+ if not self.quiet:
+ print "%s has old/modified contents" % target
+ print " overwriting it with new contents"
+ open(target, "wt").write(new_contents)
+ else:
+ if not self.quiet:
+ print "%s has old/modified contents" % target
+ print " writing new contents to %s.new" % target
+ open(target + ".new", "wt").write(new_contents)
+ # otherwise, it's up to date
+ else:
+ if not self.quiet:
+ print "populating %s" % target
+ open(target, "wt").write(new_contents)
+
+ def move_if_present(self, source, dest):
+ if os.path.exists(source):
+ if os.path.exists(dest):
+ print "Notice: %s now overrides %s" % (dest, source)
+ print " as the latter is not used by buildbot anymore."
+ print " Decide which one you want to keep."
+ else:
+ try:
+ print "Notice: Moving %s to %s." % (source, dest)
+ print " You can (and probably want to) remove it if you haven't modified this file."
+ os.renames(source, dest)
+ except Exception, e:
+ print "Error moving %s to %s: %s" % (source, dest, str(e))
+
+ def upgrade_public_html(self, files):
+ webdir = os.path.join(self.basedir, "public_html")
+ if not os.path.exists(webdir):
+ if not self.quiet:
+ print "populating public_html/"
+ os.mkdir(webdir)
+ for target, source in files.iteritems():
+ self.populate_if_missing(os.path.join(webdir, target),
+ source)
+
+ def check_master_cfg(self):
+ from buildbot.master import BuildMaster
+ from twisted.python import log, failure
+
+ master_cfg = os.path.join(self.basedir, "master.cfg")
+ if not os.path.exists(master_cfg):
+ if not self.quiet:
+ print "No master.cfg found"
+ return 1
+
+ # side-effects of loading the config file:
+
+ # for each Builder defined in c['builders'], if the status directory
+ # didn't already exist, it will be created, and the
+ # $BUILDERNAME/builder pickle might be created (with a single
+ # "builder created" event).
+
+ # we put basedir in front of sys.path, because that's how the
+ # buildmaster itself will run, and it is quite common to have the
+ # buildmaster import helper classes from other .py files in its
+ # basedir.
+
+ if sys.path[0] != self.basedir:
+ sys.path.insert(0, self.basedir)
+
+ m = BuildMaster(self.basedir)
+ # we need to route log.msg to stdout, so any problems can be seen
+ # there. But if everything goes well, I'd rather not clutter stdout
+ # with log messages. So instead we add a logObserver which gathers
+ # messages and only displays them if something goes wrong.
+ messages = []
+ log.addObserver(messages.append)
+ try:
+ # this will raise an exception if there's something wrong with
+ # the config file. Note that this BuildMaster instance is never
+ # started, so it won't actually do anything with the
+ # configuration.
+ m.loadConfig(open(master_cfg, "r"), check_synchronously_only=True)
+ except:
+ f = failure.Failure()
+ if not self.quiet:
+ print
+ for m in messages:
+ print "".join(m['message'])
+ print f
+ print
+ print "An error was detected in the master.cfg file."
+ print "Please correct the problem and run 'buildbot upgrade-master' again."
+ print
+ return 1
+ return 0
+
+DB_HELP = """
+ The --db string is evaluated to build the DB object, which specifies
+ which database the buildmaster should use to hold scheduler state and
+ status information. The default (which creates an SQLite database in
+ BASEDIR/state.sqlite) is equivalent to:
+
+ --db='DBSpec("sqlite3", basedir+"/state.sqlite"))'
+ --db='sqlite:///state.sqlite'
+
+ To use a remote MySQL database instead, use something like:
+
+ --db='mysql://bbuser:bbpasswd@dbhost/bbdb'
+"""
+
+class UpgradeMasterOptions(MakerBase):
+ optFlags = [
+ ["replace", "r", "Replace any modified files without confirmation."],
+ ]
+ optParameters = [
+ ["db", None, "sqlite:///state.sqlite",
+ "which DB to use for scheduler/status state. See below for syntax."],
+ ]
+
+ def getSynopsis(self):
+ return "Usage: buildbot upgrade-master [options] [<basedir>]"
+
+ longdesc = """
+ This command takes an existing buildmaster working directory and
+ adds/modifies the files there to work with the current version of
+ buildbot. When this command is finished, the buildmaster directory should
+ look much like a brand-new one created by the 'create-master' command.
+
+ Use this after you've upgraded your buildbot installation and before you
+ restart the buildmaster to use the new version.
+
+ If you have modified the files in your working directory, this command
+ will leave them untouched, but will put the new recommended contents in a
+ .new file (for example, if index.html has been modified, this command
+ will create index.html.new). You can then look at the new version and
+ decide how to merge its contents into your modified file.
+"""+DB_HELP+"""
+ When upgrading from a pre-0.8.0 release (which did not use a database),
+ this command will create the given database and migrate data from the old
+ pickle files into it, then move the pickle files out of the way (e.g. to
+ changes.pck.old). To revert to an older release, rename the pickle files
+ back. When you are satisfied with the new version, you can delete the old
+ pickle files.
+ """
+
+def upgradeMaster(config):
+ basedir = os.path.expanduser(config['basedir'])
+ m = Maker(config)
+ # TODO: check Makefile
+ # TODO: check TAC file
+ # check web files: index.html, default.css, robots.txt
+ m.upgrade_public_html({
+ 'bg_gradient.jpg' : util.sibpath(__file__, "../status/web/files/bg_gradient.jpg"),
+ 'default.css' : util.sibpath(__file__, "../status/web/files/default.css"),
+ 'robots.txt' : util.sibpath(__file__, "../status/web/files/robots.txt"),
+ 'favicon.ico' : util.sibpath(__file__, "../status/web/files/favicon.ico"),
+ })
+ m.populate_if_missing(os.path.join(basedir, "master.cfg.sample"),
+ util.sibpath(__file__, "sample.cfg"),
+ overwrite=True)
+ # if index.html exists, use it to override the root page tempalte
+ m.move_if_present(os.path.join(basedir, "public_html/index.html"),
+ os.path.join(basedir, "templates/root.html"))
+
+ from buildbot.db import connector, dbspec
+ spec = dbspec.DBSpec.from_url(config["db"], basedir)
+ # TODO: check that TAC file specifies the right spec
+
+ # upgrade the db
+ from buildbot.db.schema import manager
+ sm = manager.DBSchemaManager(spec, basedir)
+ sm.upgrade()
+
+ # check the configuration
+ rc = m.check_master_cfg()
+ if rc:
+ return rc
+ if not config['quiet']: print "upgrade complete"
+ return 0
+
+
+class MasterOptions(MakerBase):
+ optFlags = [
+ ["force", "f",
+ "Re-use an existing directory (will not overwrite master.cfg file)"],
+ ["relocatable", "r",
+ "Create a relocatable buildbot.tac"],
+ ]
+ optParameters = [
+ ["config", "c", "master.cfg", "name of the buildmaster config file"],
+ ["log-size", "s", "1000000",
+ "size at which to rotate twisted log files"],
+ ["log-count", "l", "None",
+ "limit the number of kept old twisted log files"],
+ ["db", None, "sqlite:///state.sqlite",
+ "which DB to use for scheduler/status state. See below for syntax."],
+ ]
+ def getSynopsis(self):
+ return "Usage: buildbot create-master [options] [<basedir>]"
+
+ longdesc = """
+ This command creates a buildmaster working directory and buildbot.tac file.
+ The master will live in <dir> and create various files there. If
+ --relocatable is given, then the resulting buildbot.tac file will be
+ written such that its containing directory is assumed to be the basedir.
+ This is generally a good idea.
+
+ At runtime, the master will read a configuration file (named
+ 'master.cfg' by default) in its basedir. This file should contain python
+ code which eventually defines a dictionary named 'BuildmasterConfig'.
+ The elements of this dictionary are used to configure the Buildmaster.
+ See doc/config.xhtml for details about what can be controlled through
+ this interface.
+""" + DB_HELP + """
+ The --db string is stored verbatim in the buildbot.tac file, and
+ evaluated as 'buildbot start' time to pass a DBConnector instance into
+ the newly-created BuildMaster object.
+ """
+
+ def postOptions(self):
+ MakerBase.postOptions(self)
+ if not re.match('^\d+$', self['log-size']):
+ raise usage.UsageError("log-size parameter needs to be an int")
+ if not re.match('^\d+$', self['log-count']) and \
+ self['log-count'] != 'None':
+ raise usage.UsageError("log-count parameter needs to be an int "+
+ " or None")
+
+
+masterTAC = """
+import os
+
+from twisted.application import service
+from buildbot.master import BuildMaster
+
+basedir = r'%(basedir)s'
+rotateLength = %(log-size)s
+maxRotatedFiles = %(log-count)s
+
+# if this is a relocatable tac file, get the directory containing the TAC
+if basedir == '.':
+ import os.path
+ basedir = os.path.abspath(os.path.dirname(__file__))
+
+application = service.Application('buildmaster')
+try:
+ from twisted.python.logfile import LogFile
+ from twisted.python.log import ILogObserver, FileLogObserver
+ logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength,
+ maxRotatedFiles=maxRotatedFiles)
+ application.setComponent(ILogObserver, FileLogObserver(logfile).emit)
+except ImportError:
+ # probably not yet twisted 8.2.0 and beyond, can't set log yet
+ pass
+
+configfile = r'%(config)s'
+
+m = BuildMaster(basedir, configfile)
+m.setServiceParent(application)
+m.log_rotation.rotateLength = rotateLength
+m.log_rotation.maxRotatedFiles = maxRotatedFiles
+
+"""
+
+def createMaster(config):
+ m = Maker(config)
+ m.mkdir()
+ m.chdir()
+ if config['relocatable']:
+ config['basedir'] = '.'
+ contents = masterTAC % config
+ m.makeTAC(contents)
+ m.sampleconfig(util.sibpath(__file__, "sample.cfg"))
+ m.public_html({
+ 'bg_gradient.jpg' : util.sibpath(__file__, "../status/web/files/bg_gradient.jpg"),
+ 'default.css' : util.sibpath(__file__, "../status/web/files/default.css"),
+ 'robots.txt' : util.sibpath(__file__, "../status/web/files/robots.txt"),
+ 'favicon.ico' : util.sibpath(__file__, "../status/web/files/favicon.ico"),
+ })
+ m.makefile()
+ m.create_db()
+
+ if not m.quiet: print "buildmaster configured in %s" % m.basedir
+
+class SlaveOptions(MakerBase):
+ optFlags = [
+ ["force", "f", "Re-use an existing directory"],
+ ["relocatable", "r",
+ "Create a relocatable buildbot.tac"],
+ ]
+ optParameters = [
+# ["name", "n", None, "Name for this build slave"],
+# ["passwd", "p", None, "Password for this build slave"],
+# ["basedir", "d", ".", "Base directory to use"],
+# ["master", "m", "localhost:8007",
+# "Location of the buildmaster (host:port)"],
+
+ ["keepalive", "k", 600,
+ "Interval at which keepalives should be sent (in seconds)"],
+ ["usepty", None, 0,
+ "(1 or 0) child processes should be run in a pty (default 0)"],
+ ["umask", None, "None",
+ "controls permissions of generated files. Use --umask=022 to be world-readable"],
+ ["maxdelay", None, 300,
+ "Maximum time between connection attempts"],
+ ["log-size", "s", "1000000",
+ "size at which to rotate twisted log files"],
+ ["log-count", "l", "None",
+ "limit the number of kept old twisted log files"],
+ ]
+
+ longdesc = """
+ This command creates a buildslave working directory and buildbot.tac
+ file. The bot will use the <name> and <passwd> arguments to authenticate
+ itself when connecting to the master. All commands are run in a
+ build-specific subdirectory of <basedir>. <master> is a string of the
+ form 'hostname:port', and specifies where the buildmaster can be reached.
+
+ <name>, <passwd>, and <master> will be provided by the buildmaster
+ administrator for your bot. You must choose <basedir> yourself.
+ """
+
+ def getSynopsis(self):
+ return "Usage: buildbot create-slave [options] <basedir> <master> <name> <passwd>"
+
+ def parseArgs(self, *args):
+ if len(args) < 4:
+ raise usage.UsageError("command needs more arguments")
+ basedir, master, name, passwd = args
+ if master[:5] == "http:":
+ raise usage.UsageError("<master> is not a URL - do not use URL")
+ self['basedir'] = basedir
+ self['master'] = master
+ self['name'] = name
+ self['passwd'] = passwd
+
+ def postOptions(self):
+ MakerBase.postOptions(self)
+ self['usepty'] = int(self['usepty'])
+ self['keepalive'] = int(self['keepalive'])
+ self['maxdelay'] = int(self['maxdelay'])
+ if self['master'].find(":") == -1:
+ raise usage.UsageError("--master must be in the form host:portnum")
+ if not re.match('^\d+$', self['log-size']):
+ raise usage.UsageError("log-size parameter needs to be an int")
+ if not re.match('^\d+$', self['log-count']) and \
+ self['log-count'] != 'None':
+ raise usage.UsageError("log-count parameter needs to be an int "+
+ " or None")
+
+slaveTAC = """
+import os
+
+from twisted.application import service
+from buildbot.slave.bot import BuildSlave
+
+basedir = r'%(basedir)s'
+rotateLength = %(log-size)s
+maxRotatedFiles = %(log-count)s
+
+# if this is a relocatable tac file, get the directory containing the TAC
+if basedir == '.':
+ import os.path
+ basedir = os.path.abspath(os.path.dirname(__file__))
+
+application = service.Application('buildslave')
+try:
+ from twisted.python.logfile import LogFile
+ from twisted.python.log import ILogObserver, FileLogObserver
+ logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength,
+ maxRotatedFiles=maxRotatedFiles)
+ application.setComponent(ILogObserver, FileLogObserver(logfile).emit)
+except ImportError:
+ # probably not yet twisted 8.2.0 and beyond, can't set log yet
+ pass
+
+buildmaster_host = '%(host)s'
+port = %(port)d
+slavename = '%(name)s'
+passwd = '%(passwd)s'
+keepalive = %(keepalive)d
+usepty = %(usepty)d
+umask = %(umask)s
+maxdelay = %(maxdelay)d
+
+s = BuildSlave(buildmaster_host, port, slavename, passwd, basedir,
+ keepalive, usepty, umask=umask, maxdelay=maxdelay)
+s.setServiceParent(application)
+
+"""
+
+def createSlave(config):
+ m = Maker(config)
+ m.mkdir()
+ m.chdir()
+ if config['relocatable']:
+ config['basedir'] = '.'
+ try:
+ master = config['master']
+ host, port = re.search(r'(.+):(\d+)', master).groups()
+ config['host'] = host
+ config['port'] = int(port)
+ except:
+ print "unparseable master location '%s'" % master
+ print " expecting something more like localhost:8007"
+ raise
+ contents = slaveTAC % config
+
+ m.makeTAC(contents, secret=True)
+
+ m.makefile()
+ m.mkinfo()
+
+ if not m.quiet: print "buildslave configured in %s" % m.basedir
+
+
+
+def stop(config, signame="TERM", wait=False):
+ import signal
+ basedir = config['basedir']
+ quiet = config['quiet']
+ os.chdir(basedir)
+ try:
+ f = open("twistd.pid", "rt")
+ except:
+ raise BuildbotNotRunningError
+ pid = int(f.read().strip())
+ signum = getattr(signal, "SIG"+signame)
+ timer = 0
+ try:
+ os.kill(pid, signum)
+ except OSError, e:
+ if e.errno != 3:
+ raise
+
+ if not wait:
+ if not quiet:
+ print "sent SIG%s to process" % signame
+ return
+ time.sleep(0.1)
+ while timer < 10:
+ # poll once per second until twistd.pid goes away, up to 10 seconds
+ try:
+ os.kill(pid, 0)
+ except OSError:
+ if not quiet:
+ print "buildbot process %d is dead" % pid
+ return
+ timer += 1
+ time.sleep(1)
+ if not quiet:
+ print "never saw process go away"
+
+def restart(config):
+ quiet = config['quiet']
+ from buildbot.scripts.startup import start
+ try:
+ stop(config, wait=True)
+ except BuildbotNotRunningError:
+ pass
+ if not quiet:
+ print "now restarting buildbot process.."
+ start(config)
+
+
+class StartOptions(MakerBase):
+ optFlags = [
+ ['quiet', 'q', "Don't display startup log messages"],
+ ]
+ def getSynopsis(self):
+ return "Usage: buildbot start [<basedir>]"
+
+class StopOptions(MakerBase):
+ def getSynopsis(self):
+ return "Usage: buildbot stop [<basedir>]"
+
+class ReconfigOptions(MakerBase):
+ optFlags = [
+ ['quiet', 'q', "Don't display log messages about reconfiguration"],
+ ]
+ def getSynopsis(self):
+ return "Usage: buildbot reconfig [<basedir>]"
+
+
+
+class RestartOptions(MakerBase):
+ optFlags = [
+ ['quiet', 'q', "Don't display startup log messages"],
+ ]
+ def getSynopsis(self):
+ return "Usage: buildbot restart [<basedir>]"
+
+class DebugClientOptions(OptionsWithOptionsFile):
+ optFlags = [
+ ['help', 'h', "Display this message"],
+ ]
+ optParameters = [
+ ["master", "m", None,
+ "Location of the buildmaster's slaveport (host:port)"],
+ ["passwd", "p", None, "Debug password to use"],
+ ]
+ buildbotOptions = [
+ [ 'debugMaster', 'passwd' ],
+ [ 'master', 'master' ],
+ ]
+
+ def parseArgs(self, *args):
+ if len(args) > 0:
+ self['master'] = args[0]
+ if len(args) > 1:
+ self['passwd'] = args[1]
+ if len(args) > 2:
+ raise usage.UsageError("I wasn't expecting so many arguments")
+
+def debugclient(config):
+ from buildbot.clients import debug
+
+ master = config.get('master')
+ if master is None:
+ raise usage.UsageError("master must be specified: on the command "
+ "line or in ~/.buildbot/options")
+
+ passwd = config.get('passwd')
+ if passwd is None:
+ raise usage.UsageError("passwd must be specified: on the command "
+ "line or in ~/.buildbot/options")
+
+ d = debug.DebugWidget(master, passwd)
+ d.run()
+
+class StatusClientOptions(OptionsWithOptionsFile):
+ optFlags = [
+ ['help', 'h', "Display this message"],
+ ]
+ optParameters = [
+ ["master", "m", None,
+ "Location of the buildmaster's status port (host:port)"],
+ ["username", "u", "statusClient", "Username performing the trial build"],
+ ["passwd", None, "clientpw", "password for PB authentication"],
+ ]
+ buildbotOptions = [
+ [ 'masterstatus', 'master' ],
+ ]
+
+ def parseArgs(self, *args):
+ if len(args) > 0:
+ self['master'] = args[0]
+ if len(args) > 1:
+ raise usage.UsageError("I wasn't expecting so many arguments")
+
+def statuslog(config):
+ from buildbot.clients import base
+ master = config.get('master')
+ if master is None:
+ raise usage.UsageError("master must be specified: on the command "
+ "line or in ~/.buildbot/options")
+ passwd = config.get('passwd')
+ username = config.get('username')
+ c = base.TextClient(master, username=username, passwd=passwd)
+ c.run()
+
+def statusgui(config):
+ from buildbot.clients import gtkPanes
+ master = config.get('master')
+ if master is None:
+ raise usage.UsageError("master must be specified: on the command "
+ "line or in ~/.buildbot/options")
+ c = gtkPanes.GtkClient(master)
+ c.run()
+
+class SendChangeOptions(OptionsWithOptionsFile):
+ def __init__(self):
+ OptionsWithOptionsFile.__init__(self)
+ self['properties'] = {}
+
+ optParameters = [
+ ("master", "m", None,
+ "Location of the buildmaster's PBListener (host:port)"),
+ ("username", "u", None, "Username performing the commit"),
+ ("repository", "R", None, "Repository specifier"),
+ ("project", "P", None, "Project specifier"),
+ ("branch", "b", None, "Branch specifier"),
+ ("category", "c", None, "Category of repository"),
+ ("revision", "r", None, "Revision specifier"),
+ ("revision_file", None, None, "Filename containing revision spec"),
+ ("property", "p", None,
+ "A property for the change, in the format: name:value"),
+ ("comments", "m", None, "log message"),
+ ("logfile", "F", None,
+ "Read the log messages from this file (- for stdin)"),
+ ("when", "w", None, "timestamp to use as the change time"),
+ ]
+
+ buildbotOptions = [
+ [ 'master', 'master' ],
+ [ 'username', 'username' ],
+ [ 'branch', 'branch' ],
+ [ 'category', 'category' ],
+ ]
+
+ def getSynopsis(self):
+ return "Usage: buildbot sendchange [options] filenames.."
+ def parseArgs(self, *args):
+ self['files'] = args
+ def opt_property(self, property):
+ name,value = property.split(':')
+ self['properties'][name] = value
+
+
+def sendchange(config, runReactor=False):
+ """Send a single change to the buildmaster's PBChangeSource. The
+ connection will be drpoped as soon as the Change has been sent."""
+ from buildbot.clients.sendchange import Sender
+
+ user = config.get('username')
+ master = config.get('master')
+ branch = config.get('branch')
+ category = config.get('category')
+ revision = config.get('revision')
+ properties = config.get('properties', {})
+ repository = config.get('repository', '')
+ project = config.get('project', '')
+ if config.get('when'):
+ when = float(config.get('when'))
+ else:
+ when = None
+ if config.get("revision_file"):
+ revision = open(config["revision_file"],"r").read()
+
+ comments = config.get('comments')
+ if not comments and config.get('logfile'):
+ if config['logfile'] == "-":
+ f = sys.stdin
+ else:
+ f = open(config['logfile'], "rt")
+ comments = f.read()
+ if comments is None:
+ comments = ""
+
+ files = config.get('files', [])
+
+ assert user, "you must provide a username"
+ assert master, "you must provide the master location"
+
+ s = Sender(master, user)
+ d = s.send(branch, revision, comments, files, category=category, when=when,
+ properties=properties, repository=repository, project=project)
+ if runReactor:
+ d.addCallbacks(s.printSuccess, s.printFailure)
+ d.addBoth(s.stop)
+ s.run()
+ return d
+
+
+class ForceOptions(OptionsWithOptionsFile):
+ optParameters = [
+ ["builder", None, None, "which Builder to start"],
+ ["branch", None, None, "which branch to build"],
+ ["revision", None, None, "which revision to build"],
+ ["reason", None, None, "the reason for starting the build"],
+ ]
+
+ def parseArgs(self, *args):
+ args = list(args)
+ if len(args) > 0:
+ if self['builder'] is not None:
+ raise usage.UsageError("--builder provided in two ways")
+ self['builder'] = args.pop(0)
+ if len(args) > 0:
+ if self['reason'] is not None:
+ raise usage.UsageError("--reason provided in two ways")
+ self['reason'] = " ".join(args)
+
+
+class TryOptions(OptionsWithOptionsFile):
+ optParameters = [
+ ["connect", "c", None,
+ "how to reach the buildmaster, either 'ssh' or 'pb'"],
+ # for ssh, use --tryhost, --username, and --trydir
+ ["tryhost", None, None,
+ "the hostname (used by ssh) for the buildmaster"],
+ ["trydir", None, None,
+ "the directory (on the tryhost) wher