def run(fs: VFs, target, cmd, cwd, env): recursive = False force = True file_list = list() if len(cmd) < 2: raise Exception('rm: missing arguments') for arg in cmd[1:]: if arg[:2] == '--': flag = arg[2:] if flag == 'recursive': recursive = True elif flag == 'force': force = True elif flag in ('help', 'version'): return None, None else: raise NotImplementedError( 'rm: flag --{:s} not implemented'.format(flag)) elif arg[0] == '-': for flag in arg[1:]: if flag in ('r', 'R'): recursive = True elif flag == 'f': force = True elif flag == 'v': pass else: raise NotImplementedError( 'rm: flag -{:s} not implemented'.format(flag)) else: file_list.append(join(cwd, arg)) for file in file_list: fs.rm(file, recursive, force) return None, None
def run(fs: VFs, target, cmd, cwd, env): parents = False dir_list = list() for arg in cmd[1:]: if arg[:2] == '--': flag = arg[2:] if flag == 'parents': parents = True elif flag in ('mode', 'verbose'): pass elif flag in ('help', 'version'): return None, None else: raise NotImplementedError( 'mkdir: flag --{:s} not implemented'.format(flag)) elif arg[0] == '-': for flag in arg[1:]: if flag == 'p': parents = True elif flag in ('m', 'v'): pass else: raise NotImplementedError( 'mkdir: flag -{:s} not implemented'.format(flag)) else: dir_list.append(join(cwd, arg)) if not dir_list: raise Exception('mkdir: missing arguments') for path in dir_list: if parents: fs.mkdirs(path) else: fs.mkdir(path) return None, None
def _get_dir_handler(fs, cwd, path): file_path = join(cwd, path) file, is_new_file = fs.get_current_dir(file_path, create_as_is=True) if is_new_file: print('WARNING: creating missing dir: {:s}'.format( file.get_full_path()), flush=True) return file
def _parse_output(fs: VFs, config: GccConfig, argv, pos): path = None if argv[pos] == '-o': pos += 1 if pos < len(argv): path = argv[pos] else: path = argv[pos][2:] if not path: raise ValueError("missing filename after '-o'") path = join(config._cwd, path) file = fs.create_new_file(path, create_dirs=True) config._output_file = (file.get_full_path(), file.get_version()) config._output_file_handler = file return pos + 1
def get_current_file(self, path, cwd=None, create_as_is=False): file_path = join(cwd, path) file = None try: file = self._get_file(file_path, VFS_FILE, False, False, False) except PathNotExist: pass if not file and create_as_is: return self.create_new_file(file_path, create_dirs=True), True elif file: if create_as_is: return VFileHandler(file), False else: return VFileHandler(file) else: raise PathNotExist
def _parse_library(fs: VFs, config: GccConfig, argv, pos): path = None if argv[pos] == '-L': pos += 1 if pos < len(argv): path = argv[pos] else: path = argv[pos][2:] if not path: raise ValueError("missing path after '-L'") if path[0] == '=': path = join(config._sysroot, path[1:]) rpath = _get_dir_handler(fs, config._cwd, path).get_full_path() if rpath not in config._library_dirs_set: config._library_dirs.append(rpath) config._library_dirs_set.add(rpath) return pos + 1
def _parse_sys_include(fs: VFs, config: GccConfig, argv, pos): path = None if argv[pos] == '-isystem': pos += 1 if pos < len(argv): path = argv[pos] else: path = argv[pos][8:] if not path: raise ValueError("missing path after '-isystem'") if path[0] == '=': path = join(config._sysroot, path[1:]) rpath = _get_dir_handler(fs, config._cwd, path).get_full_path() if (rpath not in config._default_sys_include_dirs_set) and ( rpath not in config._sys_include_dirs_set): config._sys_include_dirs.append(rpath) config._sys_include_dirs_set.add(rpath) return pos + 1
def _cp(fs, cwd, src, dst, dereference=False, dereference_command_line=False, recursive=False): src = get_abs_path(join(cwd, src)) dst = get_abs_path(join(cwd, dst)) dst_type = fs.get_type(dst) # dst exist if dst_type: if dst_type == VFS_SYMLINK: dst = fs.realpath(dst) dst_type = fs.get_type(dst) if dst_type == VFS_DIR: dst = join(dst, get_base_name(src)) dst_type = fs.get_type(dst) if dst_type: if dst_type == VFS_SYMLINK: dst = fs.realpath(dst) dst_type = fs.get_type(dst) src_type = fs.get_type(src) if not src_type: fs.create_new_file(src, None, True) src_type = VFS_FILE print('WARNING: creating missing file: {:s}'.format(src), flush=True) # raise PathNotExist('cp: file {:s} not exist.'.format(src)) if src_type == VFS_SYMLINK: if dereference or dereference_command_line: src = fs.realpath(src) src_type = fs.get_type(src) if not src_type: fs.create_new_file(src, None, True) src_type = VFS_FILE print('WARNING: creating missing file: {:s}'.format(src), flush=True) # raise PathNotExist('cp: file {:s} not exist.'.format(src)) else: if dst_type: if dst_type != VFS_FILE: raise Exception( 'cp: cannot overwrite dir {:s} with non-dir.'.format( dst)) fs.rm(dst, force=True) fs.mklink(dst, fs.readlink(src)) return None, None if src_type == VFS_DIR: if recursive: if not dst_type or dst_type == VFS_DIR: file_list = fs.list_dir(src) src_list = list() dst_list = list() if not dst_type: fs.mkdir(dst) for file in file_list: dep = _cp(fs, None, file.get_full_path(), join(dst, file.get_base_name()), dereference, False, True) if dep[0]: src_list.extend(dep[0]) dst_list.extend(dep[1]) return tuple(src_list), tuple(dst_list) else: raise Exception( 'cp: cannot overwrite dir {:s} with non-dir.'.format(dst)) return None, None else: if dst_type and dst_type != VFS_FILE: raise Exception( 'cp: cannot overwrite dir {:s} with non-dir.'.format(dst)) else: fs.mkdirs(get_dir_name(dst)) fs.copy(src, dst) sfile = fs.get_current_file(src) dfile = fs.get_current_file(dst) return ((dfile.get_full_path(), dfile.get_version()), ), ((sfile.get_full_path(), sfile.get_version()), )
def run(fs: VFs, target, cmd, cwd, env): dereference = False dereference_command_line = True recursive = False file_list = list() for arg in cmd[1:]: if arg[0] == '-': if arg[:2] == '--': flags = [arg[2:]] else: flags = arg[1:] for flag in flags: if '=' in flag: flag = flag.split('=')[0] if flag in ('r', 'R', 'recursive'): recursive = True elif flag in ('d', 'P', 'no-dereference'): dereference = False dereference_command_line = False elif flag in ('L', 'dereference'): dereference = True elif flag == 'H': dereference_command_line = True elif flag in ('a', 'archive'): dereference = False dereference_command_line = False recursive = True elif flag in ('p', 'f', 'v', 'force', 'verbose', 'preserve'): pass elif flag in ('help', 'version'): return None, None else: raise NotImplementedError( 'cp: flag {:s} not implemented'.format(flag)) else: file_list.append(arg) if len(file_list) < 2: raise Exception('cp: missing destination file operand') destination_file = file_list[-1] file_list = file_list[:-1] # cp [OPTION]... [-T] SOURCE DEST if len(file_list) == 1: return _cp(fs, cwd, file_list[0], destination_file, dereference, dereference_command_line, recursive) else: dst_dir = get_abs_path(join(cwd, destination_file)) dst_type = fs.get_type(dst_dir) if not dst_type: fs.mkdirs(dst_dir) dst_type = VFS_DIR if dst_type != VFS_DIR: raise Exception( 'cp: destination is not dir or not exist: {:s}'.format( destination_file)) src_list = list() dst_list = list() for file in file_list: dep = _cp(fs, cwd, file, join(destination_file, file), dereference, False, True) if dep[0]: src_list.extend(dep[0]) dst_list.extend(dep[1]) return tuple(src_list), tuple(dst_list)
def run(fs: VFs, target, cmd, cwd, env): no_target_directory = False sym_link = False force = False file_list = list() for arg in cmd[1:]: if arg[:2] == '--': flag = arg[2:] if flag == 'symbolic': sym_link = True elif flag == 'force': force = True elif flag == 'no-target-directory': no_target_directory = True elif flag in ('mode', 'verbose'): pass elif flag in ('help', 'version'): return None, None else: raise NotImplementedError('ln: flag --{:s} not implemented'.format(flag)) elif arg[0] == '-': for flag in arg[1:]: if flag == 's': sym_link = True elif flag == 'f': force = True elif flag == 'T': no_target_directory = True elif flag in ('m', 'v'): pass else: raise NotImplementedError('ln: flag -{:s} not implemented'.format(flag)) else: file_list.append(arg) if not file_list: raise Exception('ln: missing arguments') if not sym_link: raise NotImplementedError('ln: hard link not implemented') file_count = len(file_list) # ln [OPTION]... [-T] TARGET LINK_NAME (1st form) # ln [OPTION]... TARGET (2nd form) if file_count <= 2: target = file_list[0] # 1st form if file_count == 2: path = join(cwd, file_list[1]) # path is dir or is link to dir and create in dir if fs.get_real_type(path) == VFS_DIR and not no_target_directory: path = join(path, get_base_name(target)) # 2nd form else: path = join(cwd, get_base_name(target)) _mklink(fs, path, target, force) # ln [OPTION]... TARGET... DIRECTORY (3rd form) elif not no_target_directory: targets = file_list[:-1] dir_path = join(cwd, file_list[-1]) path_type = fs.get_real_type(dir_path) if not path_type or path_type != VFS_DIR: raise Exception('ln: target `{:s}` is not a directory'.format(dir_path)) for target in targets: path = join(dir_path, get_base_name(target)) _mklink(fs, path, target, force) else: raise Exception('ln: extra operand `{:s}`'.format(file_list[2])) return None, None
def run(fs: VFs, target, cmd, cwd, env): config = GccConfig() config._cwd = cwd config._command = target c_type = 'c' # start parsing pos = 1 argc = len(cmd) while pos < argc: key, handler = _handlers.longest_prefix(cmd[pos]) if handler: # call option parser pos = handler(fs, config, cmd, pos) else: # is input file input_file = cmd[pos] if c_type == 'c' and input_file.endswith(('.cpp', '.cxx', '.cc')): c_type = 'c++' file = _get_file_handler(fs, cwd, input_file) file_id = (file.get_full_path(), file.get_version()) if file_id not in config._input_files_set: config._input_files.append(file_id) config._input_files_set.add(file_id) pos += 1 default_include_dirs = None default_sys_include_dirs = None if target in _init_default_include_dirs: default_include_dirs = _init_default_include_dirs[target] default_sys_include_dirs = _init_default_sys_include_dirs[target] elif os.path.exists(target): default_include_dirs, default_sys_include_dirs, default_macros = _get_gcc_default_config( fs, target, c_type) _init_default_include_dirs[target] = default_include_dirs _init_default_sys_include_dirs[target] = default_sys_include_dirs _init_default_macros[target] = default_macros if default_include_dirs: for inc_dir in default_include_dirs: if inc_dir not in config._default_include_dirs_set: config._default_include_dirs.append(inc_dir) config._default_include_dirs_set.add(inc_dir) if default_sys_include_dirs: for inc_dir in default_sys_include_dirs: if inc_dir not in config._default_sys_include_dirs_set: config._default_sys_include_dirs.append(inc_dir) config._default_sys_include_dirs_set.add(inc_dir) if config._sysroot: for sys_inc_dir in ('usr/local/include', 'usr/include'): inc_dir = join(config._sysroot, sys_inc_dir) if inc_dir not in config._default_sys_include_dirs_set: config._default_sys_include_dirs.append(inc_dir) config._default_sys_include_dirs_set.add(inc_dir) for inc_dir in config._default_include_dirs_set: if inc_dir in config._include_dirs_set: config._include_dirs.remove(inc_dir) for inc_dir in config._default_sys_include_dirs_set: if inc_dir in config._sys_include_dirs_set: config._sys_include_dirs.remove(inc_dir) config._input_files = tuple(config._input_files) config._include_files = tuple(config._include_files) config._linked_libs = tuple(config._linked_libs) config._include_dirs = tuple(config._include_dirs) config._sys_include_dirs = tuple(config._sys_include_dirs) config._library_dirs = tuple(config._library_dirs) config._define_undef = tuple(config._define_undef) config._other_options = tuple(config._other_options) config._linker_options = tuple(config._linker_options) config._default_include_dirs = tuple(config._default_include_dirs) config._default_sys_include_dirs = tuple(config._default_sys_include_dirs) if config._only_do_preprocessing: if config._input_from_stdin: return None, None else: return None, config._input_files if not config._output_file: # default output file file = fs.create_new_file(join(cwd, 'a.out')) file.get_extra_data_ref().value = config config._output_file = (file.get_full_path(), file.get_version()) else: config._output_file_handler.get_extra_data_ref().value = config config._output_file_handler = None if config._input_from_stdin: return (config._output_file, ), None else: return (config._output_file, ), config._input_files
def cd(self, path): new_path = join(self.cwd, path) if self.fs.isdir(self.fs.realpath(new_path)): self.cwd = new_path else: print('{:s} is not dir.'.format(path))
def get(self, path=None): if path: return join(self.cwd, path) else: return self.cwd
def _get_file(self, path, file_type, create, overwrite, create_dirs, override_to_dir=False): ptr_node = self._root abs_path = get_abs_path(path) if abs_path == '/': if file_type & VFS_DIR: if create and overwrite: raise FileExist('file {:s} exists.'.format(abs_path)) else: return self._root.values[-1] else: raise FileTypeNotMatch( '{:s} file type {:s} not match {:s}'.format( abs_path, _type_to_string(self._root.values[-1].type), _type_to_string(file_type))) if not abs_path.startswith('/'): raise ValueError( 'path `{:s}` not absolute or not valid'.format(abs_path)) path_elements = abs_path.split('/') # loop through dirs element_count = 0 for item in path_elements[:-1]: element_count += 1 if not item: continue # 1. current node exists # 2. current node is dir current_dir = ptr_node.values[-1] # if item node is exist if item in ptr_node.children: item_node = ptr_node.children[item] item_file = item_node.values[-1] # if item exists and is dir if item_node.exist and item_file.type == VFS_DIR: # move to dir ptr_node = item_node continue # - item not exists elif not item_node.exist: # if we will create it if create_dirs: # create a new dir item_node.values.append( VDir(item_node, len(item_node.values), current_dir.version)) item_node.exist = True # move to dir ptr_node = item_node continue # - error: path not exist else: raise PathNotExist('path {:s} is not exist.'.format( join(ptr_node.path, item))) # - item exists and is symlink elif item_file.type == VFS_SYMLINK: target = join(ptr_node.path, item_file.target, *path_elements[element_count:]) # if symlink to itself if target == abs_path: raise PathNotExist('path {:s} is not exist.'.format( join(ptr_node.path, item))) # follow symlink return self._get_file(target, file_type, create, overwrite, create_dirs) # - error: item exists but is not dir or symlink else: # if override to dir if override_to_dir: item_node.values.append( VDir(item_node, len(item_node.values), current_dir.version)) # move to dir ptr_node = item_node continue raise PathNotExist('{:s} is not a dir.'.format( item_node.path)) # - item node is not exist but we will create it elif create_dirs: # create new dir node and add to current node item_node = Node(ptr_node, item) ptr_node.children[item] = item_node # create VDir for item node item_node.values.append(VDir(item_node, 0, current_dir.version)) # move to dir ptr_node = item_node continue # - error: path not exist else: raise PathNotExist('path {:s} is not exist.'.format( join(ptr_node.path, item))) # try get file in target dir file = path_elements[-1] current_dir = ptr_node.values[-1] # if file node is exist if file in ptr_node.children: file_node = ptr_node.children[file] file_value = file_node.values[-1] # if file is exist if file_node.exist: current_file = file_node.values[-1] # if we should overwrite current file if create and overwrite: # if current is file and overwrite type is file if file_type == VFS_FILE and current_file.type == VFS_FILE: # create a new file file_value = VFile(file_node, len(file_node.values), current_dir.version) file_node.values.append(file_value) # - current is symlink and overwrite type is not symlink elif not file_type & VFS_SYMLINK and current_file.type == VFS_SYMLINK: target = join(ptr_node.path, file_value.target) # if symlink to itself if target == abs_path: raise PathNotExist( 'path {:s} is not exist.'.format(abs_path)) # follow symlink return self._get_file(target, file_type, create, overwrite, create_dirs) # - current is symlink and overwrite type is symlink # - current is file and overwrite type is not file # - current is dir and try to overwrite else: raise FileExist('file {:s} exists.'.format(abs_path)) # - current is symlink and create not overwrite elif create and current_file.type == VFS_SYMLINK: target = join(ptr_node.path, file_value.target) # if symlink to itself if target == abs_path: raise PathNotExist( 'path {:s} is not exist.'.format(abs_path)) # follow symlink return self._get_file(target, file_type, create, overwrite, create_dirs) # if file is what we want if file_value.type & file_type: return file_value # - file is symlink elif file_value.type == VFS_SYMLINK: target = join(ptr_node.path, file_value.target) # if symlink to itself if target == abs_path: raise PathNotExist( 'path {:s} is not exist.'.format(abs_path)) # follow symlink return self._get_file(target, file_type, create, overwrite, create_dirs) # - error: file type not match else: raise FileTypeNotMatch( '{:s} file type {:s} not match {:s}'.format( abs_path, _type_to_string(file_value.type), _type_to_string(file_type))) # - file is not exist else: # if we will create it if create: # create a new file file_value = _create_file(file_type, file_node, len(file_node.values), current_dir.version) file_node.values.append(file_value) file_node.exist = True return file_value # - error: path not exist else: raise PathNotExist('path {:s} is not exist.'.format( join(ptr_node.path, file))) # - file node is not exist but we will create it elif create: # create new file node and add to current node file_node = Node(ptr_node, file) ptr_node.children[file] = file_node # create new file for item node file_value = _create_file(file_type, file_node, 0, current_dir.version) file_node.values.append(file_value) return file_value # - error: path not exist else: raise PathNotExist('path {:s} is not exist.'.format( join(ptr_node.path, file)))
def create_new_file(self, path, cwd=None, create_dirs=False): return VFileHandler( self._get_file(join(cwd, path), VFS_FILE, True, True, create_dirs, create_dirs))