2014-07-10 17:21:34 +00:00
import os
2016-04-27 13:51:46 +00:00
from . utils import ( exec_cmd , get_frappe , check_git_for_shallow_clone , build_assets ,
2016-03-15 11:27:48 +00:00
restart_supervisor_processes , get_cmd_output , run_frappe_cmd )
from . config . common_site_config import get_config
2014-07-10 17:21:34 +00:00
2014-07-11 09:33:07 +00:00
import logging
2014-07-21 06:10:03 +00:00
import requests
2015-02-24 07:46:22 +00:00
import semantic_version
2014-07-21 06:10:03 +00:00
import json
2015-02-24 07:46:22 +00:00
import re
import subprocess
2016-01-11 06:58:02 +00:00
logging . basicConfig ( level = " DEBUG " )
2014-07-11 09:33:07 +00:00
logger = logging . getLogger ( __name__ )
2014-07-10 17:21:34 +00:00
2015-02-24 07:46:22 +00:00
class MajorVersionUpgradeException ( Exception ) :
def __init__ ( self , message , upstream_version , local_version ) :
super ( MajorVersionUpgradeException , self ) . __init__ ( message )
self . upstream_version = upstream_version
self . local_version = local_version
2014-07-10 17:21:34 +00:00
def get_apps ( bench = ' . ' ) :
try :
with open ( os . path . join ( bench , ' sites ' , ' apps.txt ' ) ) as f :
return f . read ( ) . strip ( ) . split ( ' \n ' )
except IOError :
return [ ]
def add_to_appstxt ( app , bench = ' . ' ) :
apps = get_apps ( bench = bench )
if app not in apps :
apps . append ( app )
2014-11-20 07:30:57 +00:00
return write_appstxt ( apps , bench = bench )
def remove_from_appstxt ( app , bench = ' . ' ) :
apps = get_apps ( bench = bench )
if app in apps :
apps . remove ( app )
return write_appstxt ( apps , bench = bench )
def write_appstxt ( apps , bench = ' . ' ) :
with open ( os . path . join ( bench , ' sites ' , ' apps.txt ' ) , ' w ' ) as f :
return f . write ( ' \n ' . join ( apps ) )
2014-07-10 17:21:34 +00:00
2015-12-08 18:52:16 +00:00
def get_app ( app , git_url , branch = None , bench = ' . ' , build_asset_files = True , verbose = False ) :
2014-07-11 09:33:07 +00:00
logger . info ( ' getting app {} ' . format ( app ) )
2016-03-16 07:33:09 +00:00
shallow_clone = ' --depth 1 ' if check_git_for_shallow_clone ( ) else ' '
2014-09-12 09:30:18 +00:00
branch = ' --branch {branch} ' . format ( branch = branch ) if branch else ' '
2016-04-27 13:51:46 +00:00
2015-06-08 03:19:07 +00:00
exec_cmd ( " git clone {git_url} {branch} {shallow_clone} --origin upstream {app} " . format (
git_url = git_url ,
app = app ,
shallow_clone = shallow_clone ,
branch = branch ) ,
cwd = os . path . join ( bench , ' apps ' ) )
2014-09-30 18:45:09 +00:00
print ' installing ' , app
2015-12-08 18:52:16 +00:00
install_app ( app , bench = bench , verbose = verbose )
2014-12-03 05:35:12 +00:00
if build_asset_files :
2014-12-03 05:07:44 +00:00
build_assets ( bench = bench )
2016-02-25 08:42:44 +00:00
conf = get_config ( bench = bench )
2014-09-10 11:20:17 +00:00
if conf . get ( ' restart_supervisor_on_update ' ) :
2014-10-31 10:27:31 +00:00
restart_supervisor_processes ( bench = bench )
2014-07-10 17:21:34 +00:00
def new_app ( app , bench = ' . ' ) :
2016-04-29 10:06:46 +00:00
# For backwards compatibility
app = app . lower ( ) . replace ( " " , " _ " ) . replace ( " - " , " _ " )
2014-07-11 09:33:07 +00:00
logger . info ( ' creating new app {} ' . format ( app ) )
2015-03-06 12:48:11 +00:00
apps = os . path . abspath ( os . path . join ( bench , ' apps ' ) )
2015-03-03 11:25:03 +00:00
if FRAPPE_VERSION == 4 :
2015-06-08 03:19:07 +00:00
exec_cmd ( " {frappe} --make_app {apps} {app} " . format ( frappe = get_frappe ( bench = bench ) ,
2015-08-15 17:30:33 +00:00
apps = apps , app = app ) )
2015-03-03 11:04:35 +00:00
else :
2015-08-15 17:30:33 +00:00
run_frappe_cmd ( ' make-app ' , apps , app , bench = bench )
2014-07-10 17:21:34 +00:00
install_app ( app , bench = bench )
2015-12-08 18:52:16 +00:00
def install_app ( app , bench = ' . ' , verbose = False ) :
2014-07-11 09:33:07 +00:00
logger . info ( ' installing {} ' . format ( app ) )
2015-12-09 13:11:34 +00:00
# find_links = '--find-links={}'.format(conf.get('wheel_cache_dir')) if conf.get('wheel_cache_dir') else ''
find_links = ' '
2015-12-08 18:52:16 +00:00
exec_cmd ( " {pip} install {quiet} {find_links} -e {app} " . format (
2015-06-08 03:19:07 +00:00
pip = os . path . join ( bench , ' env ' , ' bin ' , ' pip ' ) ,
2015-12-08 18:52:16 +00:00
quiet = " -q " if not verbose else " " ,
2015-06-08 03:19:07 +00:00
app = os . path . join ( bench , ' apps ' , app ) ,
find_links = find_links ) )
2014-07-10 17:21:34 +00:00
add_to_appstxt ( app , bench = bench )
2015-03-05 09:38:39 +00:00
def pull_all_apps ( bench = ' . ' ) :
2016-02-26 06:58:01 +00:00
rebase = ' --rebase ' if get_config ( bench ) . get ( ' rebase_on_pull ' ) else ' '
2015-02-24 07:46:22 +00:00
2015-07-04 08:36:53 +00:00
for app in get_apps ( bench = bench ) :
app_dir = get_repo_dir ( app , bench = bench )
2014-07-10 17:21:34 +00:00
if os . path . exists ( os . path . join ( app_dir , ' .git ' ) ) :
2014-09-05 03:58:55 +00:00
logger . info ( ' pulling {0} ' . format ( app ) )
2015-07-04 08:36:53 +00:00
exec_cmd ( " git pull {rebase} upstream {branch} " . format ( rebase = rebase , branch = get_current_branch ( app , bench = bench ) ) , cwd = app_dir )
2014-10-30 07:08:02 +00:00
2015-05-04 04:12:25 +00:00
def is_version_upgrade ( bench = ' . ' , branch = None ) :
2015-07-04 08:36:53 +00:00
fetch_upstream ( ' frappe ' , bench = bench )
upstream_version = get_upstream_version ( ' frappe ' , bench = bench , branch = branch )
2015-02-24 07:46:22 +00:00
if not upstream_version :
2015-06-24 14:17:38 +00:00
raise Exception ( " Current branch of ' frappe ' not in upstream " )
2015-02-24 07:46:22 +00:00
2015-07-04 08:36:53 +00:00
local_version = get_major_version ( get_current_version ( ' frappe ' , bench = bench ) )
2015-02-24 07:46:22 +00:00
upstream_version = get_major_version ( upstream_version )
2015-07-04 08:36:53 +00:00
if upstream_version - local_version > 0 :
2015-08-17 10:28:01 +00:00
return ( True , local_version , upstream_version )
return ( False , local_version , upstream_version )
2015-02-24 07:46:22 +00:00
2015-02-24 09:40:30 +00:00
def get_current_frappe_version ( bench = ' . ' ) :
2015-03-03 11:09:07 +00:00
try :
2015-07-04 08:36:53 +00:00
return get_major_version ( get_current_version ( ' frappe ' , bench = bench ) )
2015-03-03 11:09:07 +00:00
except IOError :
2016-04-27 13:51:46 +00:00
return 0
2015-02-24 09:40:30 +00:00
2015-07-04 08:36:53 +00:00
def get_current_branch ( app , bench = ' . ' ) :
repo_dir = get_repo_dir ( app , bench = bench )
2014-10-30 07:08:02 +00:00
return get_cmd_output ( " basename $(git symbolic-ref -q HEAD) " , cwd = repo_dir )
2014-07-21 06:10:03 +00:00
2016-05-05 10:53:00 +00:00
def use_rq ( bench_path ) :
bench_path = os . path . abspath ( bench_path )
celery_app = os . path . join ( bench_path , ' apps ' , ' frappe ' , ' frappe ' , ' celery_app.py ' )
return not os . path . exists ( celery_app )
2015-07-04 08:36:53 +00:00
def fetch_upstream ( app , bench = ' . ' ) :
repo_dir = get_repo_dir ( app , bench = bench )
2015-02-24 07:46:22 +00:00
return exec_cmd ( " git fetch upstream " , cwd = repo_dir )
2015-07-04 08:36:53 +00:00
def get_current_version ( app , bench = ' . ' ) :
repo_dir = get_repo_dir ( app , bench = bench )
2015-02-24 07:46:22 +00:00
with open ( os . path . join ( repo_dir , ' setup.py ' ) ) as f :
return get_version_from_string ( f . read ( ) )
2015-07-04 08:36:53 +00:00
def get_upstream_version ( app , branch = None , bench = ' . ' ) :
repo_dir = get_repo_dir ( app , bench = bench )
2015-05-04 04:12:25 +00:00
if not branch :
2015-09-27 22:37:22 +00:00
branch = get_current_branch ( app , bench = bench )
2015-02-24 07:46:22 +00:00
try :
2015-05-04 04:12:25 +00:00
contents = subprocess . check_output ( [ ' git ' , ' show ' , ' upstream/ {branch} :setup.py ' . format ( branch = branch ) ] , cwd = repo_dir , stderr = subprocess . STDOUT )
2015-02-24 07:46:22 +00:00
except subprocess . CalledProcessError , e :
if " Invalid object " in e . output :
return None
else :
raise
return get_version_from_string ( contents )
2015-07-04 08:36:53 +00:00
def get_upstream_url ( app , bench = ' . ' ) :
repo_dir = get_repo_dir ( app , bench = bench )
return subprocess . check_output ( [ ' git ' , ' config ' , ' --get ' , ' remote.upstream.url ' ] , cwd = repo_dir ) . strip ( )
def get_repo_dir ( app , bench = ' . ' ) :
return os . path . join ( bench , ' apps ' , app )
2015-05-04 04:12:25 +00:00
def switch_branch ( branch , apps = None , bench = ' . ' , upgrade = False ) :
from . utils import update_requirements , backup_all_sites , patch_sites , build_assets , pre_upgrade , post_upgrade
import utils
2015-03-17 03:28:49 +00:00
apps_dir = os . path . join ( bench , ' apps ' )
2015-05-04 04:12:25 +00:00
version_upgrade = is_version_upgrade ( bench = bench , branch = branch )
2015-08-17 10:28:01 +00:00
if version_upgrade [ 0 ] and not upgrade :
raise MajorVersionUpgradeException ( " Switching to {0} will cause upgrade from {1} to {2} . Pass --upgrade to confirm " . format ( branch , version_upgrade [ 1 ] , version_upgrade [ 2 ] ) , version_upgrade [ 1 ] , version_upgrade [ 2 ] )
2015-05-04 04:12:25 +00:00
2015-03-17 03:28:49 +00:00
if not apps :
2015-09-03 06:39:16 +00:00
apps = [ ' frappe ' , ' erpnext ' ]
2015-09-03 05:58:34 +00:00
if branch == " v4.x.x " :
apps . append ( ' shopping_cart ' )
2015-03-17 03:28:49 +00:00
for app in apps :
app_dir = os . path . join ( apps_dir , app )
if os . path . exists ( app_dir ) :
2015-05-06 05:25:53 +00:00
unshallow = " --unshallow " if os . path . exists ( os . path . join ( app_dir , " .git " , " shallow " ) ) else " "
exec_cmd ( " git config --unset-all remote.upstream.fetch " , cwd = app_dir )
exec_cmd ( " git config --add remote.upstream.fetch ' +refs/heads/*:refs/remotes/upstream/* ' " , cwd = app_dir )
exec_cmd ( " git fetch upstream {unshallow} " . format ( unshallow = unshallow ) , cwd = app_dir )
2015-03-17 03:28:49 +00:00
exec_cmd ( " git checkout {branch} " . format ( branch = branch ) , cwd = app_dir )
2015-05-05 04:14:03 +00:00
exec_cmd ( " git merge upstream/ {branch} " . format ( branch = branch ) , cwd = app_dir )
2015-03-17 03:28:49 +00:00
2015-08-17 10:28:01 +00:00
if version_upgrade [ 0 ] and upgrade :
2015-05-04 04:12:25 +00:00
update_requirements ( )
2015-08-17 10:28:01 +00:00
pre_upgrade ( version_upgrade [ 1 ] , version_upgrade [ 2 ] )
2015-05-04 04:12:25 +00:00
reload ( utils )
backup_all_sites ( )
patch_sites ( )
build_assets ( )
2015-08-17 10:28:01 +00:00
post_upgrade ( version_upgrade [ 1 ] , version_upgrade [ 2 ] )
2015-05-04 04:12:25 +00:00
def switch_to_master ( apps = None , bench = ' . ' , upgrade = False ) :
switch_branch ( ' master ' , apps = apps , bench = bench , upgrade = upgrade )
2015-03-17 03:28:49 +00:00
2015-05-04 04:12:25 +00:00
def switch_to_develop ( apps = None , bench = ' . ' , upgrade = False ) :
switch_branch ( ' develop ' , apps = apps , bench = bench , upgrade = upgrade )
2015-03-17 11:20:43 +00:00
2015-05-04 04:12:25 +00:00
def switch_to_v4 ( apps = None , bench = ' . ' , upgrade = False ) :
switch_branch ( ' v4.x.x ' , apps = apps , bench = bench , upgrade = upgrade )
2015-03-17 03:28:49 +00:00
2015-08-22 23:56:29 +00:00
def switch_to_v5 ( apps = None , bench = ' . ' , upgrade = False ) :
switch_branch ( ' v5.x.x ' , apps = apps , bench = bench , upgrade = upgrade )
2015-02-24 07:46:22 +00:00
def get_version_from_string ( contents ) :
2015-06-08 03:19:07 +00:00
match = re . search ( r " ^( \ s* %s \ s*= \ s*[ ' \\ \" ])(.+?)([ ' \" ])(?sm) " % ' version ' ,
contents )
2015-02-24 07:46:22 +00:00
return match . group ( 2 )
def get_major_version ( version ) :
return semantic_version . Version ( version ) . major
2015-06-08 03:19:07 +00:00
def install_apps_from_path ( path , bench = ' . ' ) :
2014-08-01 11:11:05 +00:00
apps = get_apps_json ( path )
for app in apps :
2015-06-08 03:19:07 +00:00
get_app ( app [ ' name ' ] , app [ ' url ' ] , branch = app . get ( ' branch ' ) , bench = bench , build_asset_files = False )
2014-07-21 06:10:03 +00:00
2014-08-01 11:11:05 +00:00
def get_apps_json ( path ) :
2014-07-21 06:10:03 +00:00
if path . startswith ( ' http ' ) :
r = requests . get ( path )
return r . json ( )
else :
with open ( path ) as f :
return json . load ( f )
2015-03-03 11:04:35 +00:00
FRAPPE_VERSION = get_current_frappe_version ( )