Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
13 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
11 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. #!/usr/bin/env python2.7
  2. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  3. # MIT License. See license.txt
  4. from __future__ import unicode_literals
  5. import sys
  6. if __name__=="__main__":
  7. sys.path = [".", "lib", "app"] + sys.path
  8. import webnotes
  9. def main():
  10. parsed_args = webnotes._dict(vars(setup_parser()))
  11. fn = get_function(parsed_args)
  12. if parsed_args.get("site")=="all":
  13. for site in get_sites():
  14. args = parsed_args.copy()
  15. args["site"] = site
  16. run(fn, args)
  17. else:
  18. run(fn, parsed_args)
  19. def cmd(fn):
  20. def new_fn(*args, **kwargs):
  21. import inspect
  22. fnargs, varargs, varkw, defaults = inspect.getargspec(fn)
  23. new_kwargs = {}
  24. for a in fnargs:
  25. if a in kwargs:
  26. new_kwargs[a] = kwargs.get(a)
  27. return fn(*args, **new_kwargs)
  28. return new_fn
  29. def run(fn, args):
  30. if isinstance(args.get(fn), (list, tuple)):
  31. out = globals().get(fn)(*args.get(fn), **args)
  32. else:
  33. out = globals().get(fn)(**args)
  34. return out
  35. def get_function(args):
  36. for fn, val in args.items():
  37. if (val or isinstance(val, list)) and globals().get(fn):
  38. return fn
  39. def get_sites():
  40. import os
  41. import conf
  42. return [site for site in os.listdir(conf.sites_dir)
  43. if not os.path.islink(os.path.join(conf.sites_dir, site))
  44. and os.path.isdir(os.path.join(conf.sites_dir, site))]
  45. def setup_parser():
  46. import argparse
  47. parser = argparse.ArgumentParser(description="Run webnotes utility functions")
  48. setup_install(parser)
  49. setup_utilities(parser)
  50. setup_translation(parser)
  51. setup_git(parser)
  52. # common
  53. parser.add_argument("-f", "--force", default=False, action="store_true",
  54. help="Force execution where applicable (look for [-f] in help)")
  55. parser.add_argument("--quiet", default=True, action="store_false", dest="verbose",
  56. help="Show verbose output where applicable")
  57. parser.add_argument("--site", nargs="?", metavar="SITE-NAME or all",
  58. help="Run for a particular site")
  59. return parser.parse_args()
  60. def setup_install(parser):
  61. parser.add_argument("--install", metavar="DB-NAME", nargs=1,
  62. help="Install a new app")
  63. parser.add_argument("--root-password", nargs=1,
  64. help="Root password for new app")
  65. parser.add_argument("--reinstall", default=False, action="store_true",
  66. help="Install a fresh app in db_name specified in conf.py")
  67. parser.add_argument("--restore", metavar=("DB-NAME", "SQL-FILE"), nargs=2,
  68. help="Restore from an sql file")
  69. parser.add_argument("--install_fixtures", default=False, action="store_true",
  70. help="(Re)Install install-fixtures from app/startup/install_fixtures")
  71. parser.add_argument("--make_demo", default=False, action="store_true",
  72. help="Install demo in demo_db_name specified in conf.py")
  73. parser.add_argument("--make_demo_fresh", default=False, action="store_true",
  74. help="(Re)Install demo in demo_db_name specified in conf.py")
  75. parser.add_argument("--add_system_manager", nargs="+",
  76. metavar=("EMAIL", "[FIRST-NAME] [LAST-NAME]"), help="Add a user with all roles")
  77. def setup_utilities(parser):
  78. # update
  79. parser.add_argument("-u", "--update", nargs="*", metavar=("REMOTE", "BRANCH"),
  80. help="Perform git pull, run patches, sync schema and rebuild files/translations")
  81. parser.add_argument("--reload_gunicorn", default=False, action="store_true", help="reload gunicorn on update")
  82. parser.add_argument("--patch", nargs=1, metavar="PATCH-MODULE",
  83. help="Run a particular patch [-f]")
  84. parser.add_argument("-l", "--latest", default=False, action="store_true",
  85. help="Run patches, sync schema and rebuild files/translations")
  86. parser.add_argument("--sync_all", default=False, action="store_true",
  87. help="Reload all doctypes, pages, etc. using txt files [-f]")
  88. parser.add_argument("--update_all_sites", nargs="*", metavar=("REMOTE", "BRANCH"),
  89. help="Perform git pull, run patches, sync schema and rebuild files/translations")
  90. parser.add_argument("--reload_doc", nargs=3,
  91. metavar=('"MODULE"', '"DOCTYPE"', '"DOCNAME"'))
  92. # build
  93. parser.add_argument("-b", "--build", default=False, action="store_true",
  94. help="Minify + concatenate JS and CSS files, build translations")
  95. parser.add_argument("-w", "--watch", default=False, action="store_true",
  96. help="Watch and concatenate JS and CSS files as and when they change")
  97. # misc
  98. parser.add_argument("--backup", default=False, action="store_true",
  99. help="Take backup of database in backup folder [--with_files]")
  100. parser.add_argument("--move", default=False, action="store_true",
  101. help="Move site to different directory defined by --dest_dir")
  102. parser.add_argument("--dest_dir", nargs=1, metavar="DEST-DIR",
  103. help="Move site to different directory")
  104. parser.add_argument("--with_files", default=False, action="store_true",
  105. help="Also take backup of files")
  106. parser.add_argument("--docs", default=False, action="store_true",
  107. help="Build docs")
  108. parser.add_argument("--domain", nargs="*",
  109. help="Get or set domain in Website Settings")
  110. parser.add_argument("--make_conf", nargs="*", metavar=("DB-NAME", "DB-PASSWORD"),
  111. help="Create new conf.py file")
  112. parser.add_argument("--make_custom_server_script", nargs=1, metavar="DOCTYPE",
  113. help="Create new conf.py file")
  114. parser.add_argument("--set_admin_password", metavar='ADMIN-PASSWORD', nargs=1,
  115. help="Set administrator password")
  116. parser.add_argument("--mysql", action="store_true", help="get mysql shell for a site")
  117. parser.add_argument("--serve", action="store_true", help="Run development server")
  118. parser.add_argument("--profile", action="store_true", help="enable profiling in development server")
  119. parser.add_argument("--smtp", action="store_true", help="Run smtp debug server",
  120. dest="smtp_debug_server")
  121. parser.add_argument("--python", action="store_true", help="get python shell for a site")
  122. parser.add_argument("--get_site_status", action="store_true", help="Get site details")
  123. parser.add_argument("--update_site_config", nargs=1,
  124. metavar="SITE-CONFIG-JSON",
  125. help="Update site_config.json for a given --site")
  126. parser.add_argument("--port", default=8000, type=int, help="port for development server")
  127. # clear
  128. parser.add_argument("--clear_web", default=False, action="store_true",
  129. help="Clear website cache")
  130. parser.add_argument("--build_sitemap", default=False, action="store_true",
  131. help="Build Website Sitemap")
  132. parser.add_argument("--clear_cache", default=False, action="store_true",
  133. help="Clear cache, doctype cache and defaults")
  134. parser.add_argument("--reset_perms", default=False, action="store_true",
  135. help="Reset permissions for all doctypes")
  136. # scheduler
  137. parser.add_argument("--run_scheduler", default=False, action="store_true",
  138. help="Trigger scheduler")
  139. parser.add_argument("--run_scheduler_event", nargs=1,
  140. metavar="all | daily | weekly | monthly",
  141. help="Run a scheduler event")
  142. # replace
  143. parser.add_argument("--replace", nargs=3,
  144. metavar=("SEARCH-REGEX", "REPLACE-BY", "FILE-EXTN"),
  145. help="Multi-file search-replace [-f]")
  146. # import/export
  147. parser.add_argument("--export_doc", nargs=2, metavar=('"DOCTYPE"', '"DOCNAME"'))
  148. parser.add_argument("--export_doclist", nargs=3, metavar=("DOCTYPE", "NAME", "PATH"),
  149. help="""Export doclist as json to the given path, use '-' as name for Singles.""")
  150. parser.add_argument("--export_csv", nargs=2, metavar=("DOCTYPE", "PATH"),
  151. help="""Dump DocType as csv""")
  152. parser.add_argument("--import_doclist", nargs=1, metavar="PATH",
  153. help="""Import (insert/update) doclist. If the argument is a directory, all files ending with .json are imported""")
  154. def setup_git(parser):
  155. parser.add_argument("--pull", nargs="*", metavar=("REMOTE", "BRANCH"),
  156. help="Run git pull for both repositories")
  157. parser.add_argument("-p", "--push", nargs="*", metavar=("REMOTE", "BRANCH"),
  158. help="Run git push for both repositories")
  159. parser.add_argument("--status", default=False, action="store_true",
  160. help="Run git status for both repositories")
  161. parser.add_argument("--commit", nargs=1, metavar="COMMIT-MSG",
  162. help="Run git commit COMMIT-MSG for both repositories")
  163. parser.add_argument("--checkout", nargs=1, metavar="BRANCH",
  164. help="Run git checkout BRANCH for both repositories")
  165. parser.add_argument("--git", nargs="*", metavar="OPTIONS",
  166. help="Run git command for both repositories")
  167. def setup_translation(parser):
  168. parser.add_argument("--build_message_files", default=False, action="store_true",
  169. help="Build message files for translation")
  170. parser.add_argument("--export_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"),
  171. help="""Export all messages for a language to translation in a csv file.
  172. Example, lib/wnf.py --export_messages hi hindi.csv""")
  173. parser.add_argument("--import_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"),
  174. help="""Import messages for a language and make language files.
  175. Example, lib/wnf.py --import_messages hi hindi.csv""")
  176. parser.add_argument("--google_translate", nargs=3,
  177. metavar=("LANG-CODE", "INFILE", "OUTFILE"),
  178. help="Auto translate using Google Translate API")
  179. parser.add_argument("--translate", nargs=1, metavar="LANG-CODE",
  180. help="""Rebuild translation for the given langauge and
  181. use Google Translate to tranlate untranslated messages. use "all" """)
  182. # methods
  183. # install
  184. @cmd
  185. def install(db_name, source_sql=None, site=None, verbose=True, force=False, root_password=None, site_config=None, admin_password='admin'):
  186. from webnotes.install_lib.install import Installer
  187. inst = Installer('root', db_name=db_name, site=site, root_password=root_password, site_config=site_config)
  188. inst.install(db_name, source_sql=source_sql, verbose=verbose, force=force, admin_password=admin_password)
  189. webnotes.destroy()
  190. @cmd
  191. def reinstall(site=None, verbose=True):
  192. webnotes.init(site=site)
  193. install(webnotes.conf.db_name, site=site, verbose=verbose, force=True)
  194. @cmd
  195. def restore(db_name, source_sql, site=None, verbose=True, force=False):
  196. install(db_name, source_sql, site=site, verbose=verbose, force=force)
  197. @cmd
  198. def install_fixtures(site=None):
  199. webnotes.init(site=site)
  200. from webnotes.install_lib.install import install_fixtures
  201. install_fixtures()
  202. webnotes.destroy()
  203. @cmd
  204. def add_system_manager(email, first_name=None, last_name=None, site=None):
  205. webnotes.connect(site=site)
  206. webnotes.profile.add_system_manager(email, first_name, last_name)
  207. webnotes.conn.commit()
  208. webnotes.destroy()
  209. @cmd
  210. def make_demo(site=None):
  211. import utilities.demo.make_demo
  212. webnotes.init(site=site)
  213. utilities.demo.make_demo.make()
  214. webnotes.destroy()
  215. @cmd
  216. def make_demo_fresh(site=None):
  217. import utilities.demo.make_demo
  218. webnotes.init(site=site)
  219. utilities.demo.make_demo.make(reset=True)
  220. webnotes.destroy()
  221. # utilities
  222. @cmd
  223. def update(remote=None, branch=None, site=None, reload_gunicorn=False):
  224. pull(remote=remote, branch=branch, site=site)
  225. # maybe there are new framework changes, any consequences?
  226. reload(webnotes)
  227. if not site: build()
  228. latest(site=site)
  229. if reload_gunicorn:
  230. import subprocess
  231. subprocess.check_output("killall -HUP gunicorn".split())
  232. @cmd
  233. def latest(site=None, verbose=True):
  234. import webnotes.modules.patch_handler
  235. import webnotes.model.sync
  236. import webnotes.plugins
  237. from website.doctype.website_sitemap_config.website_sitemap_config import build_website_sitemap_config
  238. webnotes.connect(site=site)
  239. try:
  240. # run patches
  241. webnotes.local.patch_log_list = []
  242. webnotes.modules.patch_handler.run_all()
  243. if verbose:
  244. print "\n".join(webnotes.local.patch_log_list)
  245. # sync
  246. webnotes.model.sync.sync_all()
  247. # remove __init__.py from plugins
  248. webnotes.plugins.remove_init_files()
  249. # build website config if any changes in templates etc.
  250. build_website_sitemap_config()
  251. except webnotes.modules.patch_handler.PatchError, e:
  252. print "\n".join(webnotes.local.patch_log_list)
  253. raise
  254. finally:
  255. webnotes.destroy()
  256. @cmd
  257. def sync_all(site=None, force=False):
  258. import webnotes.model.sync
  259. webnotes.connect(site=site)
  260. webnotes.model.sync.sync_all(force=force)
  261. webnotes.destroy()
  262. @cmd
  263. def patch(patch_module, site=None, force=False):
  264. import webnotes.modules.patch_handler
  265. webnotes.connect(site=site)
  266. webnotes.local.patch_log_list = []
  267. webnotes.modules.patch_handler.run_single(patch_module, force=force)
  268. print "\n".join(webnotes.local.patch_log_list)
  269. webnotes.destroy()
  270. @cmd
  271. def update_all_sites(remote=None, branch=None, verbose=True):
  272. pull(remote, branch)
  273. # maybe there are new framework changes, any consequences?
  274. reload(webnotes)
  275. build()
  276. for site in get_sites():
  277. latest(site=site, verbose=verbose)
  278. @cmd
  279. def reload_doc(module, doctype, docname, site=None, force=False):
  280. webnotes.connect(site=site)
  281. webnotes.reload_doc(module, doctype, docname, force=force)
  282. webnotes.destroy()
  283. @cmd
  284. def build():
  285. import webnotes.build
  286. webnotes.build.bundle(False)
  287. @cmd
  288. def watch():
  289. import webnotes.build
  290. webnotes.build.watch(True)
  291. @cmd
  292. def backup(site=None, with_files=False, verbose=True, backup_path_db=None, backup_path_files=None):
  293. from webnotes.utils.backups import scheduled_backup
  294. webnotes.connect(site=site)
  295. odb = scheduled_backup(ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files)
  296. if verbose:
  297. from webnotes.utils import now
  298. print "database backup taken -", odb.backup_path_db, "- on", now()
  299. if with_files:
  300. print "files backup taken -", odb.backup_path_files, "- on", now()
  301. webnotes.destroy()
  302. return odb
  303. @cmd
  304. def move(site=None, dest_dir=None):
  305. import os
  306. if not dest_dir:
  307. raise Exception, "--dest_dir is required for --move"
  308. dest_dir = dest_dir[0]
  309. if not os.path.isdir(dest_dir):
  310. raise Exception, "destination is not a directory or does not exist"
  311. webnotes.init(site=site)
  312. old_path = webnotes.utils.get_site_path()
  313. new_path = os.path.join(dest_dir, site)
  314. # check if site dump of same name already exists
  315. site_dump_exists = True
  316. count = 0
  317. while site_dump_exists:
  318. final_new_path = new_path + (count and str(count) or "")
  319. site_dump_exists = os.path.exists(final_new_path)
  320. count = int(count or 0) + 1
  321. os.rename(old_path, final_new_path)
  322. webnotes.destroy()
  323. return os.path.basename(final_new_path)
  324. @cmd
  325. def docs():
  326. from core.doctype.documentation_tool.documentation_tool import write_static
  327. write_static()
  328. @cmd
  329. def domain(host_url=None, site=None):
  330. webnotes.connect(site=site)
  331. if host_url:
  332. webnotes.conn.set_value("Website Settings", None, "subdomain", host_url)
  333. webnotes.conn.commit()
  334. else:
  335. print webnotes.conn.get_value("Website Settings", None, "subdomain")
  336. webnotes.destroy()
  337. @cmd
  338. def make_conf(db_name=None, db_password=None, site=None, site_config=None):
  339. from webnotes.install_lib.install import make_conf
  340. make_conf(db_name=db_name, db_password=db_password, site=site, site_config=site_config)
  341. @cmd
  342. def make_custom_server_script(doctype, site=None):
  343. from core.doctype.custom_script.custom_script import make_custom_server_script_file
  344. webnotes.connect(site=site)
  345. make_custom_server_script_file(doctype)
  346. webnotes.destroy()
  347. # clear
  348. @cmd
  349. def clear_cache(site=None):
  350. import webnotes.sessions
  351. webnotes.connect(site=site)
  352. webnotes.sessions.clear_cache()
  353. webnotes.destroy()
  354. @cmd
  355. def clear_web(site=None):
  356. import webnotes.webutils
  357. webnotes.connect(site=site)
  358. webnotes.webutils.clear_cache()
  359. webnotes.destroy()
  360. @cmd
  361. def build_sitemap(site=None):
  362. from website.doctype.website_sitemap_config.website_sitemap_config import build_website_sitemap_config
  363. webnotes.connect(site=site)
  364. build_website_sitemap_config()
  365. webnotes.destroy()
  366. @cmd
  367. def reset_perms(site=None):
  368. webnotes.connect(site=site)
  369. for d in webnotes.conn.sql_list("""select name from `tabDocType`
  370. where ifnull(istable, 0)=0 and ifnull(custom, 0)=0"""):
  371. webnotes.clear_cache(doctype=d)
  372. webnotes.reset_perms(d)
  373. webnotes.destroy()
  374. # scheduler
  375. @cmd
  376. def run_scheduler(site=None):
  377. import webnotes.utils.scheduler
  378. webnotes.connect(site=site)
  379. print webnotes.utils.scheduler.execute()
  380. webnotes.destroy()
  381. @cmd
  382. def run_scheduler_event(event, site=None):
  383. import webnotes.utils.scheduler
  384. webnotes.connect(site=site)
  385. print webnotes.utils.scheduler.trigger("execute_" + event)
  386. webnotes.destroy()
  387. # replace
  388. @cmd
  389. def replace(search_regex, replacement, extn, force=False):
  390. print search_regex, replacement, extn
  391. replace_code('.', search_regex, replacement, extn, force=force)
  392. # import/export
  393. @cmd
  394. def export_doc(doctype, docname, site=None):
  395. import webnotes.modules
  396. webnotes.connect(site=site)
  397. webnotes.modules.export_doc(doctype, docname)
  398. webnotes.destroy()
  399. @cmd
  400. def export_doclist(doctype, name, path, site=None):
  401. from core.page.data_import_tool import data_import_tool
  402. webnotes.connect(site=site)
  403. data_import_tool.export_json(doctype, name, path)
  404. webnotes.destroy()
  405. @cmd
  406. def export_csv(doctype, path, site=None):
  407. from core.page.data_import_tool import data_import_tool
  408. webnotes.connect(site=site)
  409. data_import_tool.export_csv(doctype, path)
  410. webnotes.destroy()
  411. @cmd
  412. def import_doclist(path, site=None, force=False):
  413. from core.page.data_import_tool import data_import_tool
  414. webnotes.connect(site=site)
  415. data_import_tool.import_doclist(path, overwrite=force)
  416. webnotes.destroy()
  417. # translation
  418. @cmd
  419. def build_message_files(site=None):
  420. import webnotes.translate
  421. webnotes.connect(site=site)
  422. webnotes.translate.build_message_files()
  423. webnotes.destroy()
  424. @cmd
  425. def export_messages(lang, outfile, site=None):
  426. import webnotes.translate
  427. webnotes.connect(site=site)
  428. webnotes.translate.export_messages(lang, outfile)
  429. webnotes.destroy()
  430. @cmd
  431. def import_messages(lang, infile, site=None):
  432. import webnotes.translate
  433. webnotes.connect(site=site)
  434. webnotes.translate.import_messages(lang, infile)
  435. webnotes.destroy()
  436. @cmd
  437. def google_translate(lang, infile, outfile, site=None):
  438. import webnotes.translate
  439. webnotes.connect(site=site)
  440. webnotes.translate.google_translate(lang, infile, outfile)
  441. webnotes.destroy()
  442. @cmd
  443. def translate(lang, site=None):
  444. import webnotes.translate
  445. webnotes.connect(site=site)
  446. webnotes.translate.translate(lang)
  447. webnotes.destroy()
  448. # git
  449. @cmd
  450. def git(param):
  451. if isinstance(param, (list, tuple)):
  452. param = " ".join(param)
  453. import os
  454. os.system("""cd lib && git %s""" % param)
  455. os.system("""cd app && git %s""" % param)
  456. def get_remote_and_branch(remote=None, branch=None):
  457. if not (remote and branch):
  458. webnotes.init()
  459. if not webnotes.conf.branch:
  460. raise Exception("Please specify remote and branch")
  461. remote = remote or "origin"
  462. branch = branch or webnotes.conf.branch
  463. webnotes.destroy()
  464. return remote, branch
  465. @cmd
  466. def pull(remote=None, branch=None):
  467. remote, branch = get_remote_and_branch(remote, branch)
  468. git(("pull", remote, branch))
  469. @cmd
  470. def push(remote=None, branch=None):
  471. remote, branch = get_remote_and_branch(remote, branch)
  472. git(("push", remote, branch))
  473. @cmd
  474. def status():
  475. git("status")
  476. @cmd
  477. def commit(message):
  478. git("""commit -a -m "%s" """ % message.replace('"', '\"'))
  479. @cmd
  480. def checkout(branch):
  481. git(("checkout", branch))
  482. @cmd
  483. def set_admin_password(admin_password, site=None):
  484. import webnotes
  485. webnotes.connect(site=site)
  486. webnotes.conn.sql("""update __Auth set `password`=password(%s)
  487. where user='Administrator'""", (admin_password,))
  488. webnotes.conn.commit()
  489. webnotes.destroy()
  490. @cmd
  491. def mysql(site=None):
  492. import webnotes
  493. import commands, os
  494. msq = commands.getoutput('which mysql')
  495. webnotes.init(site=site)
  496. os.execv(msq, [msq, '-u', webnotes.conf.db_name, '-p'+webnotes.conf.db_password, webnotes.conf.db_name, '-h', webnotes.conf.db_host or "localhost"])
  497. webnotes.destroy()
  498. @cmd
  499. def python(site=None):
  500. import webnotes
  501. import commands, os
  502. python = commands.getoutput('which python')
  503. webnotes.init(site=site)
  504. if site:
  505. os.environ["site"] = site
  506. os.environ["PYTHONSTARTUP"] = os.path.join(os.path.dirname(__file__), "pythonrc.py")
  507. os.execv(python, [python])
  508. webnotes.destroy()
  509. @cmd
  510. def smtp_debug_server():
  511. import commands, os
  512. python = commands.getoutput('which python')
  513. os.execv(python, [python, '-m', "smtpd", "-n", "-c", "DebuggingServer", "localhost:25"])
  514. @cmd
  515. def serve(port=8000, profile=False):
  516. import webnotes.app
  517. webnotes.app.serve(port=port, profile=profile)
  518. def replace_code(start, txt1, txt2, extn, search=None, force=False):
  519. """replace all txt1 by txt2 in files with extension (extn)"""
  520. import webnotes.utils
  521. import os, re
  522. esc = webnotes.utils.make_esc('[]')
  523. if not search: search = esc(txt1)
  524. for wt in os.walk(start, followlinks=1):
  525. for fn in wt[2]:
  526. if fn.split('.')[-1]==extn:
  527. fpath = os.path.join(wt[0], fn)
  528. with open(fpath, 'r') as f:
  529. content = f.read()
  530. if re.search(search, content):
  531. res = search_replace_with_prompt(fpath, txt1, txt2, force)
  532. if res == 'skip':
  533. return 'skip'
  534. def search_replace_with_prompt(fpath, txt1, txt2, force=False):
  535. """ Search and replace all txt1 by txt2 in the file with confirmation"""
  536. from termcolor import colored
  537. with open(fpath, 'r') as f:
  538. content = f.readlines()
  539. tmp = []
  540. for c in content:
  541. if c.find(txt1) != -1:
  542. print fpath
  543. print colored(txt1, 'red').join(c[:-1].split(txt1))
  544. a = ''
  545. if force:
  546. c = c.replace(txt1, txt2)
  547. else:
  548. while a.lower() not in ['y', 'n', 'skip']:
  549. a = raw_input('Do you want to Change [y/n/skip]?')
  550. if a.lower() == 'y':
  551. c = c.replace(txt1, txt2)
  552. elif a.lower() == 'skip':
  553. return 'skip'
  554. tmp.append(c)
  555. with open(fpath, 'w') as f:
  556. f.write(''.join(tmp))
  557. print colored('Updated', 'green')
  558. @cmd
  559. def get_site_status(site=None, verbose=False):
  560. import webnotes
  561. import webnotes.utils
  562. from webnotes.profile import get_system_managers
  563. from core.doctype.profile.profile import get_total_users, get_active_users, \
  564. get_website_users, get_active_website_users
  565. import json
  566. webnotes.connect(site=site)
  567. ret = {
  568. 'last_backup_on': webnotes.local.conf.last_backup_on,
  569. 'active_users': get_active_users(),
  570. 'total_users': get_total_users(),
  571. 'active_website_users': get_active_website_users(),
  572. 'website_users': get_website_users(),
  573. 'system_managers': "\n".join(get_system_managers()),
  574. 'default_company': webnotes.conn.get_default("company"),
  575. 'disk_usage': webnotes.utils.get_disk_usage(),
  576. 'working_directory': webnotes.utils.get_base_path()
  577. }
  578. # country, timezone, industry
  579. control_panel_details = webnotes.conn.get_value("Control Panel", "Control Panel",
  580. ["country", "time_zone", "industry"], as_dict=True)
  581. if control_panel_details:
  582. ret.update(control_panel_details)
  583. # basic usage/progress analytics
  584. for doctype in ("Company", "Customer", "Item", "Quotation", "Sales Invoice",
  585. "Journal Voucher", "Stock Ledger Entry"):
  586. key = doctype.lower().replace(" ", "_") + "_exists"
  587. ret[key] = 1 if webnotes.conn.count(doctype) else 0
  588. webnotes.destroy()
  589. if verbose:
  590. print json.dumps(ret, indent=1, sort_keys=True)
  591. return ret
  592. @cmd
  593. def update_site_config(site_config, site, verbose=False):
  594. import json
  595. if isinstance(site_config, basestring):
  596. site_config = json.loads(site_config)
  597. webnotes.init(site=site)
  598. webnotes.conf.site_config.update(site_config)
  599. site_config_path = webnotes.get_conf_path(webnotes.conf.sites_dir, site)
  600. with open(site_config_path, "w") as f:
  601. json.dump(webnotes.conf.site_config, f, indent=1, sort_keys=True)
  602. webnotes.destroy()
  603. if __name__=="__main__":
  604. main()