You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

129 lines
4.2 KiB

  1. # Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com)
  2. #
  3. # MIT License (MIT)
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a
  6. # copy of this software and associated documentation files (the "Software"),
  7. # to deal in the Software without restriction, including without limitation
  8. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9. # and/or sell copies of the Software, and to permit persons to whom the
  10. # Software is furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  16. # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  17. # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  19. # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  20. # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. #
  22. from __future__ import unicode_literals
  23. """
  24. Execute Patch Files
  25. Patch files usually lie in the "patches" module specified by "modules_path" in defs.py
  26. To run directly
  27. python lib/wnf.py patch patch1, patch2 etc
  28. python lib/wnf.py patch -f patch1, patch2 etc
  29. where patch1, patch2 is module name
  30. """
  31. import webnotes
  32. def run_all(patch_list=None):
  33. """run all pending patches"""
  34. executed = [p[0] for p in webnotes.conn.sql("""select patch from __PatchLog""")]
  35. import patches.patch_list
  36. for patch in (patch_list or patches.patch_list.patch_list):
  37. pn = patch['patch_module'] + '.' + patch['patch_file']
  38. if pn not in executed:
  39. if not run_single(patchmodule = pn):
  40. return log(pn + ': failed: STOPPED')
  41. def reload_doc(args):
  42. """relaod a doc args {module, doctype, docname}"""
  43. import webnotes.modules
  44. run_single(method = webnotes.modules.reload_doc, methodargs = args)
  45. def run_single(patchmodule=None, method=None, methodargs=None, force=False):
  46. """run a single patch"""
  47. import conf
  48. # don't write txt files
  49. conf.developer_mode = 0
  50. if force or method or not executed(patchmodule):
  51. return execute_patch(patchmodule, method, methodargs)
  52. else:
  53. return True
  54. def execute_patch(patchmodule, method=None, methodargs=None):
  55. """execute the patch"""
  56. success = False
  57. block_user(True)
  58. webnotes.conn.begin()
  59. log('Executing %s in %s' % (patchmodule or str(methodargs), webnotes.conn.cur_db_name))
  60. try:
  61. if patchmodule:
  62. patch = __import__(patchmodule, fromlist=True)
  63. getattr(patch, 'execute')()
  64. update_patch_log(patchmodule)
  65. log('Success')
  66. elif method:
  67. method(**methodargs)
  68. webnotes.conn.commit()
  69. success = True
  70. except Exception, e:
  71. webnotes.conn.rollback()
  72. global has_errors
  73. has_errors = True
  74. tb = webnotes.getTraceback()
  75. log(tb)
  76. import os
  77. if os.environ.get('HTTP_HOST'):
  78. add_to_patch_log(tb)
  79. block_user(False)
  80. return success
  81. def add_to_patch_log(tb):
  82. """add error log to patches/patch.log"""
  83. import conf, os
  84. with open(os.path.join(conf.modules_path,'erpnext','patches','patch.log'),'a') as patchlog:
  85. patchlog.write('\n\n' + tb)
  86. def update_patch_log(patchmodule):
  87. """update patch_file in patch log"""
  88. webnotes.conn.sql("""INSERT INTO `__PatchLog` VALUES (%s, now())""", \
  89. patchmodule)
  90. def executed(patchmodule):
  91. """return True if is executed"""
  92. done = webnotes.conn.sql("""select patch from __PatchLog where patch=%s""", patchmodule)
  93. if done:
  94. print "Patch %s executed in %s" % (patchmodule, webnotes.conn.cur_db_name)
  95. return done
  96. def block_user(block):
  97. """stop/start execution till patch is run"""
  98. webnotes.conn.begin()
  99. msg = "Patches are being executed in the system. Please try again in a few moments."
  100. webnotes.conn.set_global('__session_status', block and 'stop' or None)
  101. webnotes.conn.set_global('__session_status_message', block and msg or None)
  102. webnotes.conn.commit()
  103. def setup():
  104. webnotes.conn.sql("""CREATE TABLE IF NOT EXISTS `__PatchLog` (
  105. patch TEXT, applied_on DATETIME) engine=InnoDB""")
  106. log_list = []
  107. has_errors = False
  108. def log(msg):
  109. log_list.append(msg)