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.
 
 
 
 
 
 

128 lines
4.1 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. """
  23. Execute Patch Files
  24. Patch files usually lie in the "patches" module specified by "modules_path" in defs.py
  25. To run directly
  26. python lib/wnf.py patch patch1, patch2 etc
  27. python lib/wnf.py patch -f patch1, patch2 etc
  28. where patch1, patch2 is module name
  29. """
  30. import webnotes
  31. def run_all(patch_list=None):
  32. """run all pending patches"""
  33. executed = [p[0] for p in webnotes.conn.sql("""select patch from __PatchLog""")]
  34. import patches.patch_list
  35. for patch in (patch_list or patches.patch_list.patch_list):
  36. pn = patch['patch_module'] + '.' + patch['patch_file']
  37. if pn not in executed:
  38. if not run_single(patchmodule = pn):
  39. return log(pn + ': failed: STOPPED')
  40. def reload_doc(args):
  41. """relaod a doc args {module, doctype, docname}"""
  42. import webnotes.modules
  43. run_single(method = webnotes.modules.reload_doc, methodargs = args)
  44. def run_single(patchmodule=None, method=None, methodargs=None, force=False):
  45. """run a single patch"""
  46. import conf
  47. # don't write txt files
  48. conf.developer_mode = 0
  49. if force or method or not executed(patchmodule):
  50. return execute_patch(patchmodule, method, methodargs)
  51. else:
  52. return True
  53. def execute_patch(patchmodule, method=None, methodargs=None):
  54. """execute the patch"""
  55. success = False
  56. block_user(True)
  57. webnotes.conn.begin()
  58. log('Executing %s in %s' % (patchmodule or str(methodargs), webnotes.conn.cur_db_name))
  59. try:
  60. if patchmodule:
  61. patch = __import__(patchmodule, fromlist=True)
  62. getattr(patch, 'execute')()
  63. update_patch_log(patchmodule)
  64. log('Success')
  65. elif method:
  66. method(**methodargs)
  67. webnotes.conn.commit()
  68. success = True
  69. except Exception, e:
  70. webnotes.conn.rollback()
  71. global has_errors
  72. has_errors = True
  73. tb = webnotes.getTraceback()
  74. log(tb)
  75. import os
  76. if os.environ.get('HTTP_HOST'):
  77. add_to_patch_log(tb)
  78. block_user(False)
  79. return success
  80. def add_to_patch_log(tb):
  81. """add error log to patches/patch.log"""
  82. import conf, os
  83. with open(os.path.join(conf.modules_path,'erpnext','patches','patch.log'),'a') as patchlog:
  84. patchlog.write('\n\n' + tb)
  85. def update_patch_log(patchmodule):
  86. """update patch_file in patch log"""
  87. webnotes.conn.sql("""INSERT INTO `__PatchLog` VALUES (%s, now())""", \
  88. patchmodule)
  89. def executed(patchmodule):
  90. """return True if is executed"""
  91. done = webnotes.conn.sql("""select patch from __PatchLog where patch=%s""", patchmodule)
  92. if done:
  93. print "Patch %s executed in %s" % (patchmodule, webnotes.conn.cur_db_name)
  94. return done
  95. def block_user(block):
  96. """stop/start execution till patch is run"""
  97. webnotes.conn.begin()
  98. msg = "Patches are being executed in the system. Please try again in a few moments."
  99. webnotes.conn.set_global('__session_status', block and 'stop' or None)
  100. webnotes.conn.set_global('__session_status_message', block and msg or None)
  101. webnotes.conn.commit()
  102. def setup():
  103. webnotes.conn.sql("""CREATE TABLE IF NOT EXISTS `__PatchLog` (
  104. patch TEXT, applied_on DATETIME) engine=InnoDB""")
  105. log_list = []
  106. has_errors = False
  107. def log(msg):
  108. log_list.append(msg)