def close(self, block_name, settings=None, force=False): from biicode.common.edition.open_close import close_block assert isinstance(block_name, BlockName) if block_name not in self.hive_holder.blocks: raise BiiException("Block %s is not in your project, you cannot close it" % str(block_name)) parent = self.hive_holder[block_name].parent if parent.time == -1: raise BiiException("Block %s is not published, you cannot close it." "\nIf you want to delete it, delete the folder in the filesystem." % str(block_name)) remote_block_holder = self._biiapi.get_block_holder(parent) from biicode.common.diffmerge.compare import compare changes = compare(remote_block_holder.resources, self.hive_holder[block_name].resources) if block_changed(changes, self.hive_holder[block_name], remote_block_holder) and not force: raise BiiException("Block %s has unpublished changes.\n%s\n" "Execute with --force to ignore them or publish it first." % (str(block_name), str(changes))) processor_changes = close_block(self.hive_holder, block_name) blocks_process(self.hive_holder, processor_changes, self._biiout) deps_process(self._biiapi, self.hive_holder, processor_changes, self._biiout, settings) self._edition.save_hive_changes(self.hive_holder.hive, processor_changes)
def _auto_detect_origin_info(self, origin, block_name): hive_disk_image = self.bii.hive_disk_image hive_disk_image.update_root_block() disk_blocks = hive_disk_image.disk_blocks if block_name is None and len(disk_blocks) > 1: raise BiiException('Current project blocks:\n\t' '\n\t'.join(disk_blocks) + 'Please specify block to publish' ' with "$ bii publish my_user/my_block"') try: block_name = block_name or disk_blocks.keys()[0] block_path = disk_blocks[block_name] except: raise BiiException("No block %s to publish in this project" % (block_name or "")) try: origin = detect_updated_origin(block_path) self.bii.user_io.out.info("Detected origin: %s" % str(origin)) except BiiException as exc: # Not auto detected, request input self.bii.user_io.out.warn(str(exc)) self.bii.user_io.out.info("Input origin info:") url = self.bii.user_io.request_string("Url", origin.url) branch = self.bii.user_io.request_string("Branch", origin.branch) commit = self.bii.user_io.request_string("Tag", origin.tag) origin_tag = self.bii.user_io.request_string("Commit", origin.commit) origin = OriginInfo(url, branch, commit, origin_tag) return origin
def _execute_command(path, command): try: process = Popen(command.split(" "), stdout=PIPE, stderr=PIPE, cwd=path) (output, _) = process.communicate() exit_code = process.wait() return exit_code, output except OSError: raise BiiException("%s command not found! make sure it is in PATH." % command.split(" ")[0]) except Exception: raise BiiException("Can't get '%s' remote info" % command.split(" ")[0])
def publish(self, *parameters): ''' publish one or all the blocks of the current project''' publish_args = _BiiArgParser.get_publish_params(*parameters) block_name, tag, versiontag, msg, publish_all, origin = publish_args if block_name and publish_all: raise BiiException('Do not specify block name with --all option') if publish_all and origin: raise BiiException('Do not specify --all with --remote option') if origin and origin.url is None: # Entered empty -r option origin = self._auto_detect_origin_info(origin, block_name) hive_manager = ClientHiveManager(self.bii) hive_manager.publish(block_name, tag, msg, versiontag, publish_all, origin)
def _get_target_block_name(self, block_name): """Check if block_name is a valid block or if block_name is none check if there is only one block in the hive. Otherwise it raises an exception""" blocks = self.hive_holder.blocks current_blocks = '\nCurrent project blocks:\n\t' + '\n\t'.join(blocks) if block_name is None: if len(blocks) == 1: return iter(blocks).next() else: raise BiiException('%s\nMore than one block in this project!' % current_blocks) if block_name not in self.hive_holder.blocks: raise BiiException('%s\nBlock "%s" does not exist in your project' % (current_blocks, block_name)) return block_name
def version_tag(value): '''function to avoid argparse error message override''' from biicode.common.model.version_tag import VersionTag try: return VersionTag.loads(value) except ValueError as e: raise BiiException(str(e))
def visit_Return(self, node): if not isinstance(node.value, _ast.Str): raise BiiException( 'Bad virtual file, returning other than string') ret = ComplexName(node.value.s) self.leaves.add(ret) self.lastLine = node.lineno
def upload(self, firmware): '''Uploading the firmware to Arduino''' self.bii.user_io.out.write('Uploading...') build_command = 'make' if sys.platform != 'win32' else 'mingw32-make' if platform.system() == 'Linux': build_command = " sudo %s" % build_command build_command = "%s %s-upload" % (build_command, firmware) # This is needed for Arduino Leonardo boards # see:http://nicholaskell.wordpress.com/2012/08/11/arduino-leonardo-upload-from-makefile/ arduino_settings = self.settings if arduino_settings.board == "leonardo": import serial import time ser = serial.Serial(port=arduino_settings.port, baudrate=1200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS) while not ser.isOpen(): pass ser.close() time.sleep(2) hive_paths = HivePaths(self.bii.current_folder) retcode, out = execute(build_command, self.bii.user_io, cwd=hive_paths.build) errors = out.strip().split(os.linesep) if retcode != 0 or 'Error' in errors[-1]: logger.error(out) raise BiiException('Upload failed') return True
def _publish_one(self, block_name, tag, msg, versiontag, origin): from biicode.common.publish.publish_manager import build_publish_request from biicode.common.publish.publish_manager import update_config # Check block_name or get the only one if block_name is None try: block_name = self._get_target_block_name(block_name) except BiiException as exc: raise BiiException( str(exc) + '\nPlease specify block to publish\n' 'with "$ bii publish my_user/my_block"') hive_holder = self.hive_holder request = build_publish_request(self._biiapi, hive_holder, block_name, tag, msg, versiontag, origin, self._biiout) try: self._biiout.debug("Sending publish request to server") version = self._biiapi.publish(request) except BiiException as e: raise PublishException('Publication failed in server!\n%s' % e.message) update_config(version, hive_holder) self._biiout.info('Successfully published %s\n' % str(version)) return version
def _handle_deletion(self, base, other, ret): '''handle pure deletions, not including own renames''' for k_deleted in base.deleted.keys(): if k_deleted not in base.renames: if k_deleted in other.deleted: # Both deleted if k_deleted in other.renames: new_name = other.renames[k_deleted] new_other_res = other.created[new_name] old_res = base.deleted[k_deleted] if new_other_res != old_res: self._biiout.warn( '%s: CONFLICT (deleted/renamed-modified): ' 'Deleted in %s and renamed-modified in %s' % (new_name, self.base_name, self.other_name)) ret[new_name] = other.created[new_name] other.renames.pop(k_deleted, None) other.created.pop(new_name, None) ret.pop(k_deleted, None) other.deleted.pop(k_deleted, None) #Deleted in base and modified in other elif k_deleted in other.modified: self._biiout.warn( '%s: CONFLICT (deleted/modified): ' 'Deleted in %s and modified in %s' % (k_deleted, self.base_name, self.other_name)) ret[k_deleted] = other.modified[k_deleted].new other.modified.pop(k_deleted, None) elif k_deleted in other.created: raise BiiException("How can it be possible???") #Deleted in base and not changed in other, we deleted it else: ret.pop(k_deleted, None) base.deleted.pop(k_deleted, None)
def _arduino_sdk_wizard(user_io, arduino_settings): ''' User'll set his Arduino SDK path or will select the auto-detection of the Arduino SDK path located in biicode_env folder. ''' sdks, default_sdk = get_valid_sdks(user_io, arduino_settings) sdk_path = user_io.request_string("Enter SDK number or type path", default_sdk) sdk_path = sdk_path or default_sdk or "None" try: number = int(sdk_path) except ValueError: selected_sdk = sdk_path selected_version = valid_arduino_sdk_version(sdk_path, user_io.out) if not selected_version: user_io.out.error("SDK not valid: %s" % sdk_path) selected_version = "None" else: try: selected_sdk, selected_version = sdks[number] except IndexError: raise BiiException( "Bad Index %d, please select number or type path" % number) arduino_settings.sdk = selected_sdk.replace('\\', '/') arduino_settings.version = selected_version
def arduino_settings_args(user_io, args, settings): ''' Method to select (without any wizard) from command line your SDK, port, board and automatic reset. Port and SDK arguments support "default" option to make automatically the setting selection ''' if settings.arduino is None: settings.arduino = ArduinoSettings() if not args.sdk and not settings.arduino.sdk: _, default_sdk = get_valid_sdks(user_io, settings.arduino) user_io.out.success("Your default SDK is: %s" % default_sdk) settings.arduino.sdk = default_sdk else: settings.arduino.sdk = args.sdk or settings.arduino.sdk try: valid_version = valid_arduino_sdk_version(settings.arduino.sdk) except: valid_version = None if not valid_version: raise BiiException( "No valid Arduino SDK version could be found." " Check if /your_SDK_path/lib/version.txt file exists") settings.arduino.version = valid_version if args.need_reset: settings.arduino.automatic_reset = True if args.need_reset == 'true' else None if (not args.port and not settings.arduino.port) or args.port == 'auto': settings.arduino.port = refresh_port( user_io, settings.arduino.port, reset=settings.arduino.automatic_reset, wizard=False) else: settings.arduino.port = args.port or settings.arduino.port settings.arduino.board = args.board or settings.arduino.board
def open_block(hive_holder, block_version, bii_api, biiout): '''Branches a block inside given hive''' block_name = block_version.block_name if block_name in hive_holder.blocks: parent_version = hive_holder[block_name].parent if parent_version.time == -1: parent_version = None raise BiiException( 'Block %s is already open with parent "%s"\n' 'You should close or delete it first, then try to open again' % (block_name, parent_version)) # Create the block holder block_holder = bii_api.get_block_holder(block_version) hive_holder.add_holder(block_holder) migrate_block_holder(block_holder, biiout) # Add resources from the block to the hive holder _process_resources(block_holder) # It is possible that is a published block without requirements if block_version.time > -1: open_dep_table = bii_api.get_dep_table(block_version) block_holder.requirements = open_dep_table # It is tracking the block_version block_holder.parent = block_version block_holder.commit_config()
def _handle_toolchain(self, name): """ name KEEP_CURRENT_TOOLCHAIN string means keep current. name = None means invalidate current and use default """ settings = self.hive_disk_image.settings current_toolchain = settings.cmake.toolchain if (name == KEEP_CURRENT_TOOLCHAIN): name = current_toolchain if name is None: # There was no previous toolchain return None if name and name != current_toolchain: # Toolchain change toolchain_path = os.path.join(self.bii_paths.bii, '%s_toolchain.cmake' % name) if not os.path.exists(toolchain_path): if name == "arduino": raise BiiException( "Arduino toolchain not found, please execute" " 'bii arduino:settings' first") elif name == "rpi": raise BiiException( "Raspberry Pi toolchain not found, please execute" " 'bii rpi:settings' first") else: raise BiiException("CMake %s toolchain not found" % toolchain_path) self.user_io.out.warn( 'Toolchain changed to %s, regenerating project' % toolchain_path) self.hive_disk_image.delete_build_folder() elif name is None: # Remove toolchain toolchain_path = None self.user_io.out.warn('Removing toolchain, regenerating project') self.hive_disk_image.delete_build_folder() else: # Keep old toolchain toolchain_path = os.path.join(self.bii_paths.bii, '%s_toolchain.cmake' % name) # If arduino, regenerate arduino_settings.cmake from settings # (needed if manual change without arduino:settings) if name == "arduino": regenerate_arduino_settings_cmake(self.bii) settings.cmake.toolchain = name self.hive_disk_image.settings = settings return toolchain_path
def path_line_parser(line): try: pattern, path = line.split(":") pattern = pattern.strip() path = path.strip().rstrip("/") result.append(IncludeMap(pattern, path)) except: raise BiiException("Incorrect include map: %s" % line)
def normalize(self, targets): if len(targets) != 1: raise BiiException("Incorrect input parameter %s" % targets) block_cell_name = iter(targets).next() declaration = block_cell_name.replace("/", ".") java_extension_re = re.compile("\.java$") declaration = java_extension_re.sub('', declaration) return JavaDeclaration(declaration)
def policies_line_parser(line): try: pattern, path = line.split(":") pattern = pattern.strip() tag = VersionTag.loads(path.strip()) result.append(Rule(pattern, tag)) except: raise BiiException("Incorrect rule in policies.bii: %s" % line)
def get_url_for_provider_login(self, provider): '''URL of the page where the user accepts application''' manager = self.manager_factory(provider) if not manager: raise BiiException() state_string = generate_state_string(provider) return manager.get_url_for_provider_login(state_string)
def bytes(self): """ obtain byte load, with lazy decompression from zipped array if necessary """ if self._binary is None: try: self._binary = zlib.decompress(self._compressed_bin) except IOError: raise BiiException("Error compressing load text string") return self._binary
def loads(cls, text): try: brl_block, time, tag = parse_block_version_expression(text) return cls(brl_block, time, tag) except ValueError: raise BiiException( 'Bad block version format "%s", ' 'it should be in the form user/block[([track_user/]track)]' '[:version][ @version_tag]' % text)
def parents_line_parser(line): if line.startswith('*'): line = line[1:] version = BlockVersion.loads(line) if result: raise BiiException('Impossible to have two main parents') result.append(version)
def get_access_token(self, code): payload = { 'client_id': BII_GITHUB_OAUTH_CLIENT_ID, 'client_secret': BII_GITHUB_OAUTH_CLIENT_SECRET, 'code': code } headers = {'Accept': 'application/json'} res = requests.post('https://github.com/login/oauth/access_token', params=payload, headers=headers) json = res.json() if "error" in json: raise BiiException(json["error"]) if json.get("scope", None) != self.scope: return BiiException(json["Biicode needs your email and login"]) return json["access_token"]
def load(path, size=None): '''Loads a file content''' try: with open(path, 'rb') as handle: if size is None: size = -1 return handle.read(size) except UnicodeDecodeError as e: raise BiiException("Error reading file %s : %s" % (path, e))
def _handle_renames(self, base, other, ret): '''the renames of base always win here''' for old_name, new_name in base.renames.items(): #old name deleted in other_resources, we delete old and create new if old_name in other.renames: self._old_rename(base, other, old_name, new_name, ret) elif new_name in other.renames.values(): self._new_rename(base, other, old_name, new_name, ret) else: # not in other renames raise BiiException('Merge internal error')
def publish(self, block_name, tag, msg, versiontag, publish_all, origin): """ param block_name: can be None, if just one block exist """ from biicode.common.model.version_tag import DEV if publish_all and block_name: raise BiiException('Do not specify "block name" and "all" option') if (tag is None or tag is DEV) and versiontag is not None: raise BiiException('DEV versions cannot have a version tag') if tag is None: tag = DEV self._biiout.info('Publishing using DEV tag. ' 'Previous DEV publication (if any) will be overwritten') if not publish_all: return self._publish_one(block_name, tag, msg, versiontag, origin) else: # Be careful, return array of versions return self._publish_all(tag, msg, versiontag)
def parent(self): if self.config.parent: if self.config.parent.block_name != self.block_name: raise BiiException( "A block should have same BlockName as it's parent.\n" "%s's parent is %s" % (self.block_name, self.config.parent.block_name)) return self.config.parent return self.block_name.init_version()
def _merge_regions(base, a, b): # section a[0:ia] has been disposed of, etc iz = ia = ib = 0 for zmatch, zend, amatch, aend, bmatch, bend in _find_regions(base, a, b): matchlen = zend - zmatch # invariants: # matchlen >= 0 # matchlen == (aend - amatch) # matchlen == (bend - bmatch) len_a = amatch - ia len_b = bmatch - ib len_base = zmatch - iz # invariants: # assert len_a >= 0 # assert len_b >= 0 # assert len_base >= 0 # print 'unmatched a=%d, b=%d' % (len_a, len_b) if len_a or len_b: # try to avoid actually slicing the lists same = _range_compare(a, ia, amatch, b, ib, bmatch) if same: yield 'same', ia, amatch else: equal_a = _range_compare(a, ia, amatch, base, iz, zmatch) equal_b = _range_compare(b, ib, bmatch, base, iz, zmatch) if equal_a and not equal_b: yield 'other', ib, bmatch elif equal_b and not equal_a: yield 'base', ia, amatch elif not equal_a and not equal_b: yield 'collide', iz, zmatch, ia, amatch, ib, bmatch else: raise BiiException('Internal merge error') ia = amatch ib = bmatch iz = zmatch # if the same part of the base was deleted on both sides # that's OK, we can just skip it. if matchlen > 0: # invariants: # assert ia == amatch # assert ib == bmatch # assert iz == zmatch yield 'eq', zmatch, zend iz = zend ia = aend ib = bend
def init_hive(bii, project_name=None, layout=None): """ Initializes an empty project """ user_cache = bii.user_cache out = bii.user_io.out bii_paths = bii.bii_paths if bii_paths.current_dir.startswith(bii_paths.user_bii_home): raise BiiException( 'Cannot create a project inside the user .biicode folder') try: bii_paths.project_root raise ClientException('Cannot create project inside other project') except NotInAHiveException: pass if project_name: name = ComplexName(project_name) current_dir = os.path.join(bii_paths.current_dir, name) bii_paths.current_dir = current_dir else: current_dir = bii_paths.current_dir ComplexName(os.path.basename(current_dir)) for root, _, _ in os.walk(current_dir): if os.path.exists(os.path.join(root, BII_DIR, BII_HIVE_DB)): if root == current_dir: project_name = os.path.basename(current_dir) raise ClientException('Project "%s" already exists' % project_name) raise ClientException( 'Cannot create project with other project inside:\n%s' % root) hive_disk_image = bii.hive_disk_image hive_disk_image.initialize() try: hive = Hive() hive_disk_image.hivedb.upsert_hive(hive) out.success('Successfully initialized biicode project %s' % (project_name or "")) # If an exception is launched, the hive folder is deleted except BaseException as e: out.error('An error occurred while creating the project %s' % str(e)) logger.error(traceback.format_exc()) if project_name and os.path.exists(current_dir): hive_disk_image.hivedb.disconnect() shutil.rmtree(current_dir) else: layout_content = user_cache.layout(layout) if layout_content: save(os.path.join(hive_disk_image.paths.bii, "layout.bii"), layout_content)
def monitor(self, *parameters): '''Open serial monitor This is a small utility to send and receive text messages over the serial port''' parser = argparse.ArgumentParser(description=self.monitor.__doc__, prog="bii %s:monitor" % self.group) parser.parse_args(*parameters) try: port = self.arduino.refresh_port() monitor(self, ClientHiveManager(self.bii), port) except Exception as e: raise BiiException('Cannot open serial monitor: %s' % str(e))
def update(self, block_name=None, time=None): """ a block is outdated, because someone has published from another location, and parent is not the last one in the block anymore. update is able to merge with the given time param time: Can be None=> means the last one param block_name: The block to be updated """ from biicode.common.diffmerge.update import update hive_holder = self.hive_holder # TODO: Copied from publish: refactor if block_name is None: blocks = hive_holder.blocks if len(blocks) == 1: block_name = iter(blocks).next() else: raise BiiException('More than one block in this project %s\n' 'Please specify block to update\n' 'with "$ bii update my_user/my_block"') try: block_holder = hive_holder[block_name] except KeyError: raise BiiException("Block %s is not open" % block_name) files, other_version = update(block_holder, time, self._biiapi, self._biiout) # Extra "process" after the update checkin_block_files(hive_holder, block_name, files, self._biiout) # TODO: It seems that this is the same pattern as _process_resources from open_close.py # Factorize accordingly # Extra thing: we have to force them to be saved for (_, content) in hive_holder[block_name].simple_resources: content._blob_updated = True # FIXME: Do not access private blocks_process(hive_holder, self._biiout) deps_process(self._biiapi, hive_holder, self._biiout) block_holder = hive_holder[block_name] block_holder.parent = other_version block_holder.commit_config() self._edition.save_hive_changes(hive_holder) return block_name