|
- #!/usr/bin/env python
-
- # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
- # MIT License. See license.txt
-
- from __future__ import unicode_literals
- import sys
-
- if __name__=="__main__":
- sys.path = [".", "lib", "app"] + sys.path
-
- import webnotes
-
- def main():
- parsed_args = webnotes._dict(vars(setup_parser()))
- fn = get_function(parsed_args)
- if parsed_args.get("site")=="all":
- for site in get_sites():
- args = parsed_args.copy()
- args["site"] = site
- run(fn, args)
- else:
- run(fn, parsed_args)
-
- def run(fn, args):
- out = globals().get(fn)(args.get(fn), args)
- webnotes.destroy()
- return out
-
- def get_function(args):
- for fn, val in args.items():
- if (val or isinstance(val, list)) and globals().get(fn):
- return fn
-
- def get_sites():
- pass
-
- def setup_parser():
- import argparse
- parser = argparse.ArgumentParser(description="Run webnotes utility functions")
-
- setup_install(parser)
- setup_utilities(parser)
- setup_translation(parser)
- setup_git(parser)
-
- # common
- parser.add_argument("-f", "--force", default=False, action="store_true",
- help="Force execution where applicable (look for [-f] in help)")
- parser.add_argument("--site", nargs="?", metavar="SITE-NAME or all",
- help="Run for a particular site")
-
- return parser.parse_args()
-
- def setup_install(parser):
- parser.add_argument("--install", metavar="DB-NAME", nargs=1,
- help="Install a new app")
- parser.add_argument("--reinstall", default=False, action="store_true",
- help="Install a fresh app in db_name specified in conf.py")
- parser.add_argument("--restore", metavar=("DB-NAME", "SQL-FILE"), nargs=2,
- help="Restore from an sql file")
- parser.add_argument("--install_fixtures", default=False, action="store_true",
- help="(Re)Install install-fixtures from app/startup/install_fixtures")
- parser.add_argument("--make_demo", default=False, action="store_true",
- help="Install demo in demo_db_name specified in conf.py")
- parser.add_argument("--make_demo_fresh", default=False, action="store_true",
- help="(Re)Install demo in demo_db_name specified in conf.py")
-
- def setup_utilities(parser):
- # update
- parser.add_argument("-u", "--update", nargs="*", metavar=("REMOTE", "BRANCH"),
- help="Perform git pull, run patches, sync schema and rebuild files/translations")
- parser.add_argument("--patch", nargs=1, metavar="PATCH-MODULE",
- help="Run a particular patch [-f]")
- parser.add_argument("-l", "--latest", default=False, action="store_true",
- help="Run patches, sync schema and rebuild files/translations")
- parser.add_argument("--sync_all", default=False, action="store_true",
- help="Reload all doctypes, pages, etc. using txt files [-f]")
- parser.add_argument("--reload_doc", nargs=3,
- metavar=('"MODULE"', '"DOCTYPE"', '"DOCNAME"'))
-
- # build
- parser.add_argument("-b", "--build", default=False, action="store_true",
- help="Minify + concatenate JS and CSS files, build translations")
- parser.add_argument("-w", "--watch", default=False, action="store_true",
- help="Watch and concatenate JS and CSS files as and when they change")
-
- # misc
- parser.add_argument("--backup", default=False, action="store_true",
- help="Take backup of database in backup folder [--with_files]")
- parser.add_argument("--with_files", default=False, action="store_true",
- help="Also take backup of files")
- parser.add_argument("--docs", default=False, action="store_true",
- help="Build docs")
- parser.add_argument("--domain", nargs="*",
- help="Get or set domain in Website Settings")
- parser.add_argument("--make_conf", nargs="*", metavar=("DB-NAME", "DB-PASSWORD"),
- help="Create new conf.py file")
-
- # clear
- parser.add_argument("--clear_web", default=False, action="store_true",
- help="Clear website cache")
- parser.add_argument("--clear_cache", default=False, action="store_true",
- help="Clear cache, doctype cache and defaults")
- parser.add_argument("--reset_perms", default=False, action="store_true",
- help="Reset permissions for all doctypes")
-
- # scheduler
- parser.add_argument("--run_scheduler", default=False, action="store_true",
- help="Trigger scheduler")
- parser.add_argument("--run_scheduler_event", nargs=1,
- metavar="all | daily | weekly | monthly",
- help="Run a scheduler event")
-
- # replace
- parser.add_argument("--replace", nargs=3,
- metavar=("SEARCH-REGEX", "REPLACE-BY", "FILE-EXTN"),
- help="Multi-file search-replace [-f]")
-
- # import/export
- parser.add_argument("--export_doc", nargs=2, metavar=('"DOCTYPE"', '"DOCNAME"'))
- parser.add_argument("--export_doclist", nargs=3, metavar=("DOCTYPE", "NAME", "PATH"),
- help="""Export doclist as json to the given path, use '-' as name for Singles.""")
- parser.add_argument("--export_csv", nargs=2, metavar=("DOCTYPE", "PATH"),
- help="""Dump DocType as csv""")
- parser.add_argument("--import_doclist", nargs=1, metavar="PATH",
- help="""Import (insert/update) doclist. If the argument is a directory, all files ending with .json are imported""")
-
- def setup_git(parser):
- parser.add_argument("--pull", nargs="*", metavar=("REMOTE", "BRANCH"),
- help="Run git pull for both repositories")
- parser.add_argument("-p", "--push", nargs="*", metavar=("REMOTE", "BRANCH"),
- help="Run git push for both repositories")
- parser.add_argument("--status", default=False, action="store_true",
- help="Run git status for both repositories")
- parser.add_argument("--commit", nargs=1, metavar="COMMIT-MSG",
- help="Run git commit COMMIT-MSG for both repositories")
- parser.add_argument("--checkout", nargs=1, metavar="BRANCH",
- help="Run git checkout BRANCH for both repositories")
- parser.add_argument("--git", nargs="*", metavar="OPTIONS",
- help="Run git command for both repositories")
-
-
- def setup_translation(parser):
- parser.add_argument("--build_message_files", default=False, action="store_true",
- help="Build message files for translation")
- parser.add_argument("--export_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"),
- help="""Export all messages for a language to translation in a csv file.
- Example, lib/wnf.py --export_messages hi hindi.csv""")
- parser.add_argument("--import_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"),
- help="""Import messages for a language and make language files.
- Example, lib/wnf.py --import_messages hi hindi.csv""")
- parser.add_argument("--google_translate", nargs=3,
- metavar=("LANG-CODE", "INFILE", "OUTFILE"),
- help="Auto translate using Google Translate API")
- parser.add_argument("--translate", nargs=1, metavar="LANG-CODE",
- help="""Rebuild translation for the given langauge and
- use Google Translate to tranlate untranslated messages. use "all" """)
-
- # methods
-
- # install
- def _install(val, args):
- from webnotes.install_lib.install import Installer
- inst = Installer('root', db_name=val[0], site=args.site)
- inst.install(*val, verbose=1, force=args.force)
-
- def install(val, args):
- _install(val, args)
-
- # install
- def reinstall(val, args):
- webnotes.init(site=args.site)
- _install([webnotes.conf.db_name], args)
-
- def restore(val, args):
- _install(val, args)
-
- def install_fixtures(val, args):
- webnotes.init(site=args.site)
- from webnotes.install_lib.install import install_fixtures
- install_fixtures()
-
- def make_demo(val, args):
- import utilities.demo.make_demo
- webnotes.init(site=args.site)
- utilities.demo.make_demo.make()
-
- def make_demo_fresh(val, args):
- import utilities.demo.make_demo
- webnotes.init(site=args.site)
- utilities.demo.make_demo.make(reset=True)
-
- # utilities
- def update(val, args):
- pull(val, args)
- reload(webnotes)
- latest(val, args)
-
- def latest(val, args):
- import webnotes.modules.patch_handler
- import webnotes.model.sync
-
- webnotes.connect(site=args.site)
-
- # run patches
- webnotes.modules.patch_handler.log_list = []
- webnotes.modules.patch_handler.run_all()
- print "\n".join(webnotes.modules.patch_handler.log_list)
-
- # sync
- webnotes.model.sync.sync_all()
-
- # build
- build(val, args)
-
- def sync_all(val, args):
- import webnotes.model.sync
- webnotes.connect(site=args.site)
- webnotes.model.sync.sync_all(force=args.force)
-
- def patch(val, args):
- import webnotes.modules.patch_handler
- webnotes.connect(site=args.site)
- webnotes.modules.patch_handler.log_list = []
- webnotes.modules.patch_handler.run_single(val[0], force=args.force)
- print "\n".join(webnotes.modules.patch_handler.log_list)
-
- def reload_doc(val, args):
- webnotes.connect(site=args.site)
- webnotes.reload_doc(val[0], val[1], val[2], force=args.force)
-
- def build(val, args):
- import webnotes.build
- webnotes.build.bundle(False)
-
- def watch(val, args):
- import webnotes.build
- webnotes.build.watch(True)
-
- def backup(val, args):
- from webnotes.utils.backups import scheduled_backup
- webnotes.connect(site=args.site)
- scheduled_backup(ignore_files=not args.with_files)
-
- def docs(val, args):
- from core.doctype.documentation_tool.documentation_tool import write_static
- write_static()
-
- def domain(val, args):
- webnotes.connect(site=args.site)
- if val:
- webnotes.conn.set_value("Website Settings", None, "subdomain", val[0])
- webnotes.conn.commit()
- else:
- print webnotes.conn.get_value("Website Settings", None, "subdomain")
-
- def make_conf(val, args):
- from webnotes.install_lib.install import make_conf
- make_conf(*val, site=args.site)
-
- # clear
- def clear_cache(val, args):
- import webnotes.sessions
- webnotes.connect(site=args.site)
- webnotes.sessions.clear_cache()
-
- def clear_web(val, args):
- import webnotes.webutils
- webnotes.connect(site=args.site)
- webnotes.webutils.clear_cache()
-
- def reset_perms(val, args):
- webnotes.connect(site=args.site)
- for d in webnotes.conn.sql_list("""select name from `tabDocType`
- where ifnull(istable, 0)=0 and ifnull(custom, 0)=0"""):
- webnotes.clear_cache(doctype=d)
- webnotes.reset_perms(d)
-
- # scheduler
- def run_scheduler(val, args):
- import webnotes.utils.scheduler
- webnotes.connect(site=args.site)
- print webnotes.utils.scheduler.execute()
-
- def run_scheduler_event(val, args):
- import webnotes.utils.scheduler
- webnotes.connect(site=args.site)
- print webnotes.utils.scheduler.trigger("execute_" + val[0])
-
- # replace
- def replace(val, args):
- print val
- replace_code('.', *val, force=args.force)
-
- # import/export
- def export_doc(val, args):
- import webnotes.modules
- webnotes.connect(site=args.site)
- webnotes.modules.export_doc(*val)
-
- def export_doclist(val, args):
- from core.page.data_import_tool import data_import_tool
- webnotes.connect(site=args.site)
- data_import_tool.export_json(*val)
-
- def export_csv(val, args):
- from core.page.data_import_tool import data_import_tool
- webnotes.connect(site=args.site)
- data_import_tool.export_csv(*val)
-
- def import_doclist(val, args):
- from core.page.data_import_tool import data_import_tool
- webnotes.connect(site=args.site)
- data_import_tool.import_doclist(*val)
-
- # translation
- def build_message_files(val, args):
- import webnotes.translate
- webnotes.connect(site=args.site)
- webnotes.translate.build_message_files()
-
- def export_messages(val, args):
- import webnotes.translate
- webnotes.connect(site=args.site)
- webnotes.translate.export_messages(*val)
-
- def import_messages(val, args):
- import webnotes.translate
- webnotes.connect(site=args.site)
- webnotes.translate.import_messages(*val)
-
- def google_translate(val, args):
- import webnotes.translate
- webnotes.connect(site=args.site)
- webnotes.translate.google_translate(*val)
-
- def translate(val, args):
- import webnotes.translate
- webnotes.connect(site=args.site)
- webnotes.translate.translate(*val)
-
- # git
- def git(val, args=None):
- cmd = val
- if isinstance(val, (list, tuple)):
- cmd = " ".join(val)
- import os
- os.system("""cd lib && git %s""" % cmd)
- os.system("""cd app && git %s""" % cmd)
-
- def pull(val, args=None):
- if not val:
- webnotes.init(site=args.site)
- val = ("origin", webnotes.conf.branch or "master")
- git(("pull", val[0], val[1]))
-
- def push(val, args=None):
- if not val:
- webnotes.init(site=args.site)
- val = ("origin", webnotes.conf.branch or "master")
- git(("push", val[0], val[1]))
-
- def status(val, args=None):
- git("status")
-
- def commit(val, args=None):
- git("""commit -a -m "%s" """ % val[0].replace('"', '\"'))
-
- def checkout(val, args=None):
- git(("checkout", val[0]))
-
- def replace_code(start, txt1, txt2, extn, search=None, force=False):
- """replace all txt1 by txt2 in files with extension (extn)"""
- import webnotes.utils
- import os, re
- esc = webnotes.utils.make_esc('[]')
- if not search: search = esc(txt1)
- for wt in os.walk(start, followlinks=1):
- for fn in wt[2]:
- if fn.split('.')[-1]==extn:
- fpath = os.path.join(wt[0], fn)
- with open(fpath, 'r') as f:
- content = f.read()
-
- if re.search(search, content):
- res = search_replace_with_prompt(fpath, txt1, txt2, force)
- if res == 'skip':
- return 'skip'
-
-
- def search_replace_with_prompt(fpath, txt1, txt2, force=False):
- """ Search and replace all txt1 by txt2 in the file with confirmation"""
- from termcolor import colored
- with open(fpath, 'r') as f:
- content = f.readlines()
-
- tmp = []
- for c in content:
- if c.find(txt1) != -1:
- print fpath
- print colored(txt1, 'red').join(c[:-1].split(txt1))
- a = ''
- if force:
- c = c.replace(txt1, txt2)
- else:
- while a.lower() not in ['y', 'n', 'skip']:
- a = raw_input('Do you want to Change [y/n/skip]?')
- if a.lower() == 'y':
- c = c.replace(txt1, txt2)
- elif a.lower() == 'skip':
- return 'skip'
- tmp.append(c)
-
- with open(fpath, 'w') as f:
- f.write(''.join(tmp))
- print colored('Updated', 'green')
-
- if __name__=="__main__":
- main()
|