comparison setup.py @ 1100:2be46f391cfa

setup: SAT_INSTALL environment variable handles "clean" and "purge" options
author souliane <souliane@mailoo.org>
date Tue, 15 Jul 2014 13:37:50 +0200
parents a32ef03d4af0
children 8e15eeb3cfc3
comparison
equal deleted inserted replaced
1099:1baa116501fa 1100:2be46f391cfa
1 #!/usr/bin/env python2 1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT: a jabber client 4 # SAT: a jabber client
5 # Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org)
6 # Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org)
6 7
7 # This program is free software: you can redistribute it and/or modify 8 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by 9 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or 10 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version. 11 # (at your option) any later version.
24 from distutils.file_util import copy_file 25 from distutils.file_util import copy_file
25 import os 26 import os
26 import sys 27 import sys
27 import subprocess 28 import subprocess
28 from stat import ST_MODE 29 from stat import ST_MODE
30 import shutil
31
29 32
30 NAME = 'sat' 33 NAME = 'sat'
31 LAUNCH_DAEMON_COMMAND = 'sat' 34 LAUNCH_DAEMON_COMMAND = 'sat'
32 35
33 ENV_SAT_INSTALL = "SAT_INSTALL" # environment variable to customise installation 36 ENV_SAT_INSTALL = "SAT_INSTALL" # environment variable to customise installation
34 NO_PREINSTALL_OPT = 'nopreinstall' # skip all preinstallation checks 37 NO_PREINSTALL_OPT = 'nopreinstall' # skip all preinstallation checks
35 AUTO_DEB_OPT = 'autodeb' # automaticaly install debs 38 AUTO_DEB_OPT = 'autodeb' # automaticaly install debs
36 NO_X_OPT = 'nox' # don't install X dependant packages 39 NO_X_OPT = 'nox' # don't install X dependant packages
40 CLEAN_OPT = 'clean' # remove previous installation directories
41 PURGE_OPT = 'purge' # remove building and previous installation directories
42
37 43
38 class MercurialException(Exception): 44 class MercurialException(Exception):
39 pass 45 pass
40 46
41 47
73 sh_file.write(sh_buffer) 79 sh_file.write(sh_buffer)
74 80
75 def custom_create_links(self): 81 def custom_create_links(self):
76 """Create symbolic links to executables""" 82 """Create symbolic links to executables"""
77 # the script which launch the daemon 83 # the script which launch the daemon
78 links = [(self.sh_script_path, LAUNCH_DAEMON_COMMAND)] 84 for source, dest in self.sh_script_links:
79 for source, dest in links: 85 if os.path.islink(dest) and os.readlink(dest) != source:
80 dest_name, copied = copy_file(source, os.path.join(self.install_scripts, dest), link='sym') 86 os.remove(dest) # copy_file doesn't force the link update
87 dest_name, copied = copy_file(source, dest, link='sym')
81 assert (copied) 88 assert (copied)
82 # we change the perm in the same way as in the original install_scripts 89 # we change the perm in the same way as in the original install_scripts
83 mode = ((os.stat(dest_name)[ST_MODE]) | 0555) & 07777 90 mode = ((os.stat(dest_name)[ST_MODE]) | 0555) & 07777
84 os.chmod(dest_name, mode) 91 os.chmod(dest_name, mode)
85 92
86 def run(self): 93 def run(self):
94 self.sh_script_path = os.path.join(self.install_lib, NAME, 'sat.sh')
95 self.sh_script_links = [(self.sh_script_path, os.path.join(self.install_scripts, LAUNCH_DAEMON_COMMAND))]
96 sys.stdout.write('running pre installation stuff\n')
97 sys.stdout.flush()
98 if PURGE_OPT in install_opt:
99 self.purge()
100 elif CLEAN_OPT in install_opt:
101 self.clean()
87 install.run(self) 102 install.run(self)
88 sys.stdout.write('running post installation stuff\n') 103 sys.stdout.write('running post installation stuff\n')
89 sys.stdout.flush() 104 sys.stdout.flush()
90 self.sh_script_path = os.path.join(self.install_lib, 'sat', 'sat.sh')
91 self.primitivus_path = os.path.join(self.install_lib, 'sat_frontends', 'primitivus')
92 self.custom_auto_options() 105 self.custom_auto_options()
93 self.custom_create_links() 106 self.custom_create_links()
107
108 def confirm(self, message):
109 """Ask the user for a confirmation"""
110 message += 'Proceed'
111 while True:
112 res = raw_input("%s (y/n)? " % message)
113 if res not in ['y', 'Y', 'n', 'N']:
114 print "Your response ('%s') was not one of the expected responses: y, n" % res
115 message = 'Proceed'
116 continue
117 if res in ('y', 'Y'):
118 return True
119 return False
120
121 def clean(self, message=None, to_remove=None):
122 """Clean previous installation directories
123
124 @param message (str): to use a non-default confirmation message
125 @param to_remove (str): extra files/directories to remove
126 """
127 if message is None:
128 message = "Cleaning previous installation directories"
129 if to_remove is None:
130 to_remove = []
131 to_remove.extend([os.path.join(self.install_lib, NAME),
132 os.path.join(self.install_data, 'share', 'doc', NAME),
133 os.path.join(self.install_lib, "%s-py%s.egg-info" % (self.config_vars['dist_fullname'], self.config_vars['py_version_short'])),
134 ])
135 for source, dest in self.sh_script_links:
136 if os.path.islink(dest):
137 to_remove.append(dest)
138
139 for script in ('jp', 'wix', 'primitivus'):
140 dest = os.path.join(self.install_scripts, script)
141 if os.path.exists(dest):
142 to_remove.append(dest)
143
144 message = "%s:\n%s\n" % (message, "\n".join([" %s" % path for path in to_remove]))
145 if not self.confirm(message):
146 return
147 sys.stdout.write('cleaning previous installation directories...\n')
148 sys.stdout.flush()
149 for path in to_remove:
150 if os.path.isdir(path):
151 shutil.rmtree(path, ignore_errors=True)
152 else:
153 os.remove(path)
154
155 def purge(self):
156 """Clean building and previous installation directories"""
157 message = "Cleaning building and previous installation directories"
158 to_remove = [os.path.join(os.getcwd(), 'build')]
159 self.clean(message, to_remove)
94 160
95 161
96 def preinstall_check(install_opt): 162 def preinstall_check(install_opt):
97 """Check presence of problematic dependencies, and try to install them with package manager 163 """Check presence of problematic dependencies, and try to install them with package manager
98 This ugly stuff is necessary as distributions are not installed correctly with setuptools/distribute 164 This ugly stuff is necessary as distributions are not installed correctly with setuptools/distribute
119 hg_installed = subprocess.call('which hg', stdout=open('/dev/null', 'w'), shell=True) == 0 185 hg_installed = subprocess.call('which hg', stdout=open('/dev/null', 'w'), shell=True) == 0
120 if not hg_installed: 186 if not hg_installed:
121 modules_toinstall.append('mercurial')""" # hg can be installed from pypi 187 modules_toinstall.append('mercurial')""" # hg can be installed from pypi
122 188
123 if modules_toinstall: 189 if modules_toinstall:
124 if AUTO_DEB_OPT in install_opt: # auto debian installation is requested 190 if AUTO_DEB_OPT in install_opt: # auto debian installation is requested
125 # are we on a distribution using apt ? 191 # are we on a distribution using apt ?
126 apt_path = subprocess.Popen('which apt-get', stdout=subprocess.PIPE, shell=True).communicate()[0][:-1] 192 apt_path = subprocess.Popen('which apt-get', stdout=subprocess.PIPE, shell=True).communicate()[0][:-1]
127 else: 193 else:
128 apt_path = None 194 apt_path = None
129 195
143 # some packages can't be automatically installed, we print their name for manual installation 209 # some packages can't be automatically installed, we print their name for manual installation
144 sys.stdout.write("You should install the following dependencies with your distribution recommanded tool before installing %s:\n" % NAME) 210 sys.stdout.write("You should install the following dependencies with your distribution recommanded tool before installing %s:\n" % NAME)
145 for module_name in not_installed: 211 for module_name in not_installed:
146 sys.stdout.write("- %s (Debian name: %s)\n" % (module_name, package[module_name])) 212 sys.stdout.write("- %s (Debian name: %s)\n" % (module_name, package[module_name]))
147 sys.exit(2) 213 sys.exit(2)
214
148 215
149 if sys.argv[1].lower() in ['egg_info', 'install']: 216 if sys.argv[1].lower() in ['egg_info', 'install']:
150 # we only check dependencies if egg_info or install is used 217 # we only check dependencies if egg_info or install is used
151 install_opt = os.environ.get(ENV_SAT_INSTALL, "").split() 218 install_opt = os.environ.get(ENV_SAT_INSTALL, "").split()
152 if not NO_PREINSTALL_OPT in install_opt: # user can force preinstall skipping 219 if not NO_PREINSTALL_OPT in install_opt: # user can force preinstall skipping