def install_dependencies(modules): for module_name, module_help in modules: try: import_module(module_name) except ImportError: if pip_installed: decision = ask_user( 'It looks like you don\'t have `{name}` package. Install it now?' .format(name=module_name), variants=['y', 'n'], ) if decision == 'y': try: rc = pip.main(['install', module_name]) if rc: # Some error occured raise ConfigError('PIP error: {}'.format(rc)) except BaseException as e: tell_user( 'You should install `{name}` manually. Installation instructions are available at {help}.' .format(name=module_name, help=module_help)) raise else: tell_user( 'You should install `{name}` manually. Installation instructions are available at {help}.' .format(name=module_name, help=module_help)) raise ConfigError('Unable to proceed...') else: tell_user( 'It looks like you don\'t have `{name}` package. You should install it manually. Installation instructions are available at {help}.' .format(name=module_name, help=module_help)) raise ConfigError('Unable to proceed...')
def check_recent_modifications(self): # Если есть файлы в статусе RECENTLY_MODIFIED, предупреждаем пользователя. recently_modified_files = self._select_files(FILE_RECENTLY_MODIFIED) if recently_modified_files: tell_user( '\nSome files on the server were modified by another user(s) not long ago:' ) for file in recently_modified_files: tell_user(' {file} by {user} at {time}'.format( file=file.get_path(PATH_ABSOLUTE), user=file._changed['who'], time=file._changed['when'])) answer = ask_user( 'Do you still want to continue?', variants=['n', 'y'], ) if answer == 'n': raise BuildError('Operation cancelled')
config['roots']['include'] = {} config['roots']['include']['path'] = 'include/conduit' config['roots']['include']['ignore'] = [ 'Credentials.inc.php', 'Settings.inc.php', 'KhinkoReminder.php', ] # Определяем, где находится проект. По идее он должен быть в родительском каталоге текущего. parent_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) if not find_missing_roots(parent_dir, config['roots']): project_dir = parent_dir else: while True: project_dir = ask_user( 'Where is your project located (enter empty string for abort)?', case_sensitive=True, ) if project_dir == '': raise ConfigError('Abort requested') project_dir = os.path.abspath(project_dir) missing_dirs = find_missing_roots(project_dir, config['roots']) if not missing_dirs: break for dir in missing_dirs: tell_user('Directory {} not found'.format(dir)) config['local'] = {}
def synchronize_all(self): # Директории dirs_to_create = self._select_dirs(FILE_NEW) dirs_to_delete = self._select_dirs(FILE_REMOTE_ONLY) # Файлы files_to_update = self._select_files(FILE_MODIFIED, FILE_RECENTLY_MODIFIED, FILE_NEW) files_to_delete = self._select_files(FILE_REMOTE_ONLY) if not any((files_to_update, files_to_delete, dirs_to_create, dirs_to_delete)): raise BuildError('Everything is up to date. No actions required.') # Покажем пользователю, какие изменения мы планируем произвести на сервере. if dirs_to_create: tell_user('\nFollowing directories will be created on the server:') for dir in dirs_to_create: tell_user(' ' + dir.get_path(PATH_ABSOLUTE | PATH_REMOTE)) if dirs_to_delete: tell_user( '\nFollowing directories will be deleted from the server:') for dir in dirs_to_delete: tell_user(' ' + dir.get_path(PATH_ABSOLUTE | PATH_REMOTE)) if files_to_update: tell_user('\nFollowing files will be uploaded to the server:') for file in files_to_update: tell_user(' ' + file.get_path(PATH_ABSOLUTE)) if files_to_delete: tell_user('\nFollowing files will be deleted from the server:') for file in files_to_delete: tell_user(' ' + file.get_path(PATH_ABSOLUTE | PATH_REMOTE)) answer = ask_user( 'Do you wish to start?', variants=['y', 'n'], ) if answer == 'n': raise BuildError('Operation cancelled') # Apply changes self.connect_to_ftp() try: for dir in dirs_to_create: dir.upload_to_server(self._ftp) tell_user('{} created'.format(dir)) for file in files_to_update: # minify and upload file file.upload_to_server(self._ftp, self._remote_file_list) tell_user('{} updated'.format(file)) for file in files_to_delete: file.delete_from_server(self._ftp, self._remote_file_list) tell_user('{} deleted'.format(file)) for dir in dirs_to_delete: dir.delete_from_server(self._ftp) tell_user('{} deleted'.format(file)) finally: self.write_remote_file_list() self.unlock_mutex() self.disconnect_from_ftp() tell_user('Mission accomplished')
def process_minified_files(self): # Если на локальной машине обнаружены минифицированные файлы, предлагаем их удалить на фиг. minified_files = self._select_files(FILE_MINIFIED) if minified_files: tell_user('There are minified files in the local repository:') for file in minified_files: tell_user(' ' + file.get_path(PATH_ABSOLUTE)) tell_user( 'Generally files are minified on the fly and stored only server-side.' ) answer = ask_user( 'What do you want to do with listed files?', variants=['d', 'i', 'g', '?'], descriptions=[ 'delete', 'ignore', 'add to ignore-list', 'decide individually' ], ) if answer == '?': # Ask again for every file decisions = [] tell_user( '\nWARNING. Changes are not applied interactively. So you can cancel everything by selecting `abort`.' ) for file in minified_files: answer = ask_user( 'What do you want to do with {file}?'.format( file=file.get_path(PATH_ABSOLUTE)), variants=['d', 'i', 'g', 'a'], descriptions=[ 'delete', 'ignore', 'add to ignore-list', 'abort' ], ) if answer == 'a': raise BuildError('Operation cancelled') else: decisions.append(answer) else: decisions = [answer for file in minified_files] update_config = False for file, decision in zip(minified_files, decisions): if decision == 'd': # Delete file file_name = file.get_path(PATH_ABSOLUTE) os.unlink(file_name) tell_user('File deleted: {}'.format(file_name)) elif decision == 'g': # Add file to ignore-list try: local_config['roots'][file.get_path( PATH_ROOT_NAME)]['ignore'].append( file.get_path(PATH_POSIX)) except KeyError: local_config['roots'][file.get_path( PATH_ROOT_NAME)]['ignore'] = [ file.get_path(PATH_POSIX) ] update_config = True tell_user('File added to ignore-list: {}'.format( file.get_path(PATH_ABSOLUTE))) if update_config: local_config.write()
return self def __exit__(self, type, value, traceback): try: self.disconnect_from_ftp() except: pass #------------------------------------------------------------------------------- # Определяем сервер try: server = sys.argv[1] except IndexError: server = ask_user('Enter FTP alias') # TODO: Добавить режим force --- игнорируем оглавление with Builder(server) as builder: try: builder.analyze_local_repository() builder.analyze_remote_repository() builder.synchronize_all() except MutexError as e: user, time = str(e).split('\t') tell_user( 'User {user} works on the site right now ({time}). Unable to proceed...' .format( user=user, time=time,