25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

124 lines
3.5 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. """
  5. Execute Patch Files
  6. To run directly
  7. python lib/wnf.py patch patch1, patch2 etc
  8. python lib/wnf.py patch -f patch1, patch2 etc
  9. where patch1, patch2 is module name
  10. """
  11. import webnotes, os
  12. class PatchError(Exception): pass
  13. def run_all():
  14. """run all pending patches"""
  15. executed = [p[0] for p in webnotes.conn.sql("""select patch from `tabPatch Log`""")]
  16. for patch in get_all_patches():
  17. if patch and (patch not in executed):
  18. if not run_single(patchmodule = patch):
  19. log(patch + ': failed: STOPPED')
  20. raise PatchError(patch)
  21. def get_all_patches():
  22. patches = []
  23. for app in webnotes.get_installed_apps():
  24. patches.extend(webnotes.get_file_items(webnotes.get_pymodule_path(app, "patches.txt")))
  25. return patches
  26. def reload_doc(args):
  27. import webnotes.modules
  28. run_single(method = webnotes.modules.reload_doc, methodargs = args)
  29. def run_single(patchmodule=None, method=None, methodargs=None, force=False):
  30. from webnotes import conf
  31. # don't write txt files
  32. conf.developer_mode = 0
  33. if force or method or not executed(patchmodule):
  34. return execute_patch(patchmodule, method, methodargs)
  35. else:
  36. return True
  37. def execute_patch(patchmodule, method=None, methodargs=None):
  38. """execute the patch"""
  39. success = False
  40. block_user(True)
  41. webnotes.conn.begin()
  42. try:
  43. log('Executing %s in %s' % (patchmodule or str(methodargs), webnotes.conn.cur_db_name))
  44. if patchmodule:
  45. if patchmodule.startswith("execute:"):
  46. exec patchmodule.split("execute:")[1] in globals()
  47. else:
  48. webnotes.get_attr(patchmodule + ".execute")()
  49. update_patch_log(patchmodule)
  50. elif method:
  51. method(**methodargs)
  52. webnotes.conn.commit()
  53. success = True
  54. except Exception, e:
  55. webnotes.conn.rollback()
  56. tb = webnotes.get_traceback()
  57. log(tb)
  58. import os
  59. if webnotes.request:
  60. add_to_patch_log(tb)
  61. block_user(False)
  62. if success:
  63. log('Success')
  64. return success
  65. def add_to_patch_log(tb):
  66. """add error log to patches/patch.log"""
  67. import conf, os
  68. # TODO use get_site_base_path
  69. with open(os.path.join(os.path.dirname(conf.__file__), 'app', 'patches','patch.log'),'a') as patchlog:
  70. patchlog.write('\n\n' + tb)
  71. def update_patch_log(patchmodule):
  72. """update patch_file in patch log"""
  73. if webnotes.conn.table_exists("__PatchLog"):
  74. webnotes.conn.sql("""INSERT INTO `__PatchLog` VALUES (%s, now())""", \
  75. patchmodule)
  76. else:
  77. webnotes.doc({"doctype": "Patch Log", "patch": patchmodule}).insert()
  78. def executed(patchmodule):
  79. """return True if is executed"""
  80. if webnotes.conn.table_exists("__PatchLog"):
  81. done = webnotes.conn.sql("""select patch from __PatchLog where patch=%s""", patchmodule)
  82. else:
  83. done = webnotes.conn.get_value("Patch Log", {"patch": patchmodule})
  84. if done:
  85. print "Patch %s executed in %s" % (patchmodule, webnotes.conn.cur_db_name)
  86. return done
  87. def block_user(block):
  88. """stop/start execution till patch is run"""
  89. webnotes.conn.begin()
  90. msg = "Patches are being executed in the system. Please try again in a few moments."
  91. webnotes.conn.set_global('__session_status', block and 'stop' or None)
  92. webnotes.conn.set_global('__session_status_message', block and msg or None)
  93. webnotes.conn.commit()
  94. def setup():
  95. webnotes.conn.sql("""CREATE TABLE IF NOT EXISTS `__PatchLog` (
  96. patch TEXT, applied_on DATETIME) engine=InnoDB""")
  97. def log(msg):
  98. if getattr(webnotes.local, "patch_log_list", None) is None:
  99. webnotes.local.patch_log_list = []
  100. webnotes.local.patch_log_list.append(msg)