def _parse_spec(self, spec): # auto convert spec string if type(spec) is str: try: spec = Spec.parse(spec) except ValueError as e: log_path.error("error parsing spec: %r -> %s", spec, e) return None # check spec append = spec.get_append() name = spec.get_name() cfg = spec.get_cfg() elements = spec.get_src_list() if len(elements) == 0: log_path.error("no elements in assign: %r", spec) return None # append? if append: assign = self.get_assign(name) if assign: log_path.info( "appending to existing assign: name='%s': %r", name, elements ) assign.append(elements) return assign log_path.warning("can't append to non-existing assign: '%s'", name) # fall through log_path.info("create new assign: name='%s': %r", name, elements) return Assign(name, elements, cfg)
def ami_path_exists(self, cwd_lock, ami_path): sys_path = self.ami_to_sys_path(cwd_lock, ami_path, mustExist=True) exists = os.path.exists(str(sys_path)) log_path.info( "ami_path_exists: path='%s' -> sys_path='%s' -> exists=%s", ami_path, sys_path, exists) return exists
def sys_to_ami_path(self, sys_path): """try to map an absolute system path back to an amiga path if multiple volumes overlap then take the shortest amiga path return ami_path or None if sys_path can't be mapped """ if not os.path.isabs(sys_path): sys_path = resolve_sys_path(sys_path) log_path.debug("vol: sys_to_ami_path: resolved rel path: %s", sys_path) res_len = None result = None for volume in self.volumes: vol_sys_path = volume.get_path() cp = os.path.commonprefix([vol_sys_path, sys_path]) if cp == vol_sys_path: remainder = sys_path[len(vol_sys_path):] n = len(remainder) if n > 0 and remainder[0] == '/': remainder = remainder[1:] n -= 1 # get volume name and build amiga path vol_name = volume.get_name() ami_path = vol_name + ":" + remainder log_path.debug( "vol: sys_to_ami_path: sys='%s' -> ami='%s'", sys_path, ami_path) if result is None or n < res_len: result = ami_path res_len = n # return best result log_path.info( "vol: sys_to_ami_path: sys='%s' -> ami=%s", sys_path, result) return result
def add_assign(self, spec): assign = self._parse_spec(spec) if assign is None: return None # check name: is volume? lo_name = assign.get_lo_name() if self.vol_mgr.is_volume(lo_name): log_path.error("assign with a volume name is not allowed: %s", lo_name) return None # check name: duplicate assign elif lo_name in self.assigns_by_name: # after setup do not allow duplicate volumes if self.is_setup: log_path.error("duplicate assign: %s", lo_name) return None # before setup simply overwrite existing assign else: old_assign = self.assigns_by_name[lo_name] log_path.info("overwriting assign: %s", old_assign) self.assigns.remove(old_assign) del self.assigns_by_name[lo_name] # after global setup try to setup assign immediately if self.is_setup: if not assign.setup(self): log_path.error("error setting up assign: %s", assign) return None assign.is_setup = True # finally add assign log_path.info("adding assign: %s", assign) self.assigns_by_name[lo_name] = assign self.assigns.append(assign) return assign
def ami_abs_path(self, cwd_lock, path): """return absolute amiga path from given path""" env = self._get_lock_env(cwd_lock) abs_path = self.abspath(path, env=env) log_path.info("ami_abs_path: path='%s' -> abs_path='%s'", path, abs_path) return str(abs_path)
def _add_auto_volumes(self): vm = self.get_vol_mgr() am = self.get_assign_mgr() # require a default 'system' volume if none is given if vm.get_num_volumes() == 0: log_path.info("no volume exists: auto adding default 'system:' volume") if not vm.add_volume('system:?create'): return False # run through auto volumes for av in self.auto_volumes: av = av.lower() if not am.is_assign(av) and not vm.is_volume(av): if av == 'root': spec = "root:/" elif av == 'ram': spec = "ram:?temp" else: log_path.error("invalid auto volume: '%s'", av) return False # add auto volume log_path.info("auto adding volume: %s", spec) if not vm.add_volume(spec): return False # done return True
def _add_auto_volumes(self): vm = self.get_vol_mgr() am = self.get_assign_mgr() # require a default 'system' volume if none is given if vm.get_num_volumes() == 0: log_path.info( "no volume exists: auto adding default 'system:' volume") if not vm.add_volume('system:?create'): return False # run through auto volumes for av in self.auto_volumes: av = av.lower() if not am.is_assign(av) and not vm.is_volume(av): if av == 'root': spec = "root:/" elif av == 'ram': spec = "ram:?temp" else: log_path.error("invalid auto volume: '%s'", av) return False # add auto volume log_path.info("auto adding volume: %s", spec) if not vm.add_volume(spec): return False # done return True
def sys_to_ami_path(self, sys_path): """try to map an absolute system path back to an amiga path if multiple volumes overlap then take the shortest amiga path return ami_path or None if sys_path can't be mapped """ if not os.path.isabs(sys_path): log_path.error("vol: sys_to_ami_path: no abs path: '%s'", sys_path) return None res_len = None result = None for vol_sys_path in self.sys2volume: cp = os.path.commonprefix([vol_sys_path, sys_path]) if cp == vol_sys_path: remainder = sys_path[len(vol_sys_path):] n = len(remainder) if n > 0 and remainder[0] == '/': remainder = remainder[1:] n -= 1 # get volume name and build amiga path vol_name = self.sys2volume[vol_sys_path] vol_name = self.orig_names[vol_name] ami_path = vol_name + ":" + remainder log_path.debug("vol: sys_to_ami_path: sys='%s' -> ami='%s'", sys_path, ami_path) if result is None or n < res_len: result = ami_path res_len = n # return best result log_path.info("vol: sys_to_ami_path: sys='%s' -> ami=%s", sys_path, result) return result
def add_volume(self, spec): # get volume for spec volume = self._parse_spec(spec) if volume is None: log_path.error("invalid volume spec: '%s'", spec) return None # check if volume name already exists? lo_name = volume.get_lo_name() if lo_name in self.vols_by_name: # after setup do not allow duplicate volumes if self.is_setup: log_path.error("duplicate volume name: '%s'", volume.get_name()) return None # before setup simply overwrite existing volume else: old_volume = self.vols_by_name[lo_name] log_path.info("overwriting volume: %s", old_volume) self.volumes.remove(old_volume) del self.vols_by_name[lo_name] # after global setup try to setup volume immediately if self.is_setup: if not volume.setup(): log_path.error("error setting up volume: %s", volume) return None volume.is_setup = True # finally add volume log_path.info("adding volume: %s", volume) self.vols_by_name[lo_name] = volume self.volumes.append(volume) return volume
def _add_auto_assigns(self): vm = self.get_vol_mgr() am = self.get_assign_mgr() # setup 'sys:' assign if not am.is_assign('sys') and not vm.is_volume('sys'): # try to map to system: if not am.is_assign('system') and not vm.is_volume('system'): log_path.info( "no sys: defined: auto adding default 'system:' volume") if not vm.add_volume('system:?create'): return False spec = "sys:system:" if not am.add_assign(spec): return False # add auto assigns for aa in self.auto_assigns: aa = aa.lower() if not am.is_assign(aa) and not vm.is_volume(aa): if aa == 't': vol = 'ram' else: vol = 'sys' opt = "" if self.auto_assigns_mkdir: opt = "?create" spec = "%s:%s:%s%s" % (aa, vol, aa, opt) log_path.info("adding auto assign: %s", spec) if not am.add_assign(spec): return False # done return True
def shutdown(self): # shutdown all volumes log_path.debug("shutting down volumes") for volume in self.volumes: log_path.info("cleaning up volume: %s", volume) volume.shutdown() volume.is_setup = False
def _parse_spec(self, spec): # auto convert spec string if type(spec) is str: try: spec = Spec.parse(spec) except ValueError as e: log_path.error("error parsing spec: %r -> %s", spec, e) return None # check spec append = spec.get_append() name = spec.get_name() cfg = spec.get_cfg() elements = spec.get_src_list() if len(elements) == 0: log_path.error("no elements in assign: %r", spec) return None # append? if append: assign = self.get_assign(name) if assign: log_path.info("appending to existing assign: name='%s': %r", name, elements) assign.append(elements) return assign log_path.warn("can't append to non-existing assign: '%s'", name) # fall through log_path.info("create new assign: name='%s': %r", name, elements) return Assign(name, elements, cfg)
def _add_auto_assigns(self): vm = self.get_vol_mgr() am = self.get_assign_mgr() # setup 'sys:' assign if not am.is_assign('sys') and not vm.is_volume('sys'): # try to map to system: if not am.is_assign('system') and not vm.is_volume('system'): log_path.info("no sys: defined: auto adding default 'system:' volume") if not vm.add_volume('system:?create'): return False spec = "sys:system:" if not am.add_assign(spec): return False # add auto assigns for aa in self.auto_assigns: aa = aa.lower() if not am.is_assign(aa) and not vm.is_volume(aa): if aa == 't': vol = 'ram' else: vol = 'sys' opt = "" if self.auto_assigns_mkdir: opt = "?create" spec = "%s:%s:%s%s" % (aa, vol, aa, opt) log_path.info("adding auto assign: %s", spec) if not am.add_assign(spec): return False # done return True
def ami_to_sys_path(self, cwd_lock, ami_path, searchMulti=False, mustExist=False): env = self._get_lock_env(cwd_lock) paths = self.volpaths(ami_path, env=env) if len(paths) == 0: log_path.info("ami_to_sys_path: ami_path='%s' -> None") return None # now we have paths with volume:abs/path sys_path = None # search for existing multi assign if searchMulti or mustExist: for npath in paths: # first try to find existing path in all locations spath = self.to_sys_path(str(npath)) if spath and os.path.exists(spath): sys_path = spath break # nothing found -> try first path if sys_path is None and not mustExist: sys_path = self.to_sys_path(str(paths[0])) log_path.info( "ami_to_sys_path: ami_path='%s'" " -> volpaths=%s -> sys_path='%s'", ami_path, ",".join(map(str, paths)), sys_path, ) return sys_path
def ami_voldir_of_path(self, cwd_lock, path): env = self._get_lock_env(cwd_lock) vol_path = self.volpath(path, env=env) voldir = vol_path.absdirname() log_path.info("ami_voldir_of_path: path='%s' -> voldir='%s'", path, voldir) return voldir
def ami_name_of_path(self, cwd_lock, path): env = self._get_lock_env(cwd_lock) abs_path = self.abspath(path, env=env) name = abs_path.filename() if name is None: name = abs_path.prefix() + ":" log_path.info("ami_name_of_path: path='%s' -> name='%s'", path, name) return name
def ami_abs_parent_path(self, path): """return absolute parent path of given path or same if already parent""" ami_path = self.volpath(AmiPath(path)) parent = ami_path.parent() if parent is None: parent = ami_path log_path.info("ami_abs_parent_path: path='%s' -> parent='%s", path, parent) return str(parent)
def ami_volume_of_path(self, path): ami_path = AmiPath(path) p = ami_path.prefix() if p is None: log_path.error("ami_volume_of_path: expect absolute path: '%s'", path) return None else: log_path.info("ami_volume_of_path: path='%s' -> volume='%s'", path, p) return p
def _create_path(self, path): # try to create path try: log_path.info("creating volume dir: %s", path) os.makedirs(path) return path except OSError as e: log_path.error("error creating volume dir: %s -> %s", path, e) return None
def sys_to_ami_path(self, sys_path): ami_path = self.from_sys_path(sys_path) log_path.info( "sys_to_ami_path: sys_path='%s' -> abs_path='%s' " "-> ami_path='%s'", sys_path, ami_path, ) return ami_path
def ami_list_dir(self, cwd_lock, ami_path): sys_path = self.ami_to_sys_path(cwd_lock, ami_path, mustExist=True) if sys_path is None: return None if not os.path.isdir(str(sys_path)): return None files = os.listdir(str(sys_path)) log_path.info("ami_list_dir: path='%s' -> sys_path='%s' -> files=%s", ami_path, sys_path, files) return files
def del_volume(self, name): lo_name = name.lower() if lo_name not in self.volume2sys: return False sys_path = self.volume2sys[lo_name] del self.volume2sys[lo_name] del self.sys2volume[sys_path] del self.orig_names[lo_name] log_path.info("del volume: '%s:' -> %s", name, sys_path) return True
def del_assign(self, name): lo_name = name.lower() if lo_name not in self.assigns_by_name: return False a = self.assigns_by_name[lo_name] a.shutdown() a.is_setup = False self.assigns.remove(a) del self.assigns_by_name[lo_name] log_path.info("delete assign: %s", a) return True
def del_assign(self, name): lo_name = name.lower() if self.assigns.has_key(lo_name): alist = self.assigns[lo_name] log_path.info("del assign: name='%s' -> paths=%s", name, alist) del self.assigns[lo_name] del self.orig_names[lo_name] return True else: log_path.error("assign not found: %s", name) return False
def del_volume(self, name): lo_name = name.lower() if lo_name not in self.vols_by_name: return False volume = self.vols_by_name[lo_name] volume.shutdown() volume.is_setup = False self.volumes.remove(volume) del self.vols_by_name[lo_name] log_path.info("delete volume: %s", volume) return True
def ami_to_sys_path(self, ami_path, fast=False): """Map an Amiga path to a system path. An absolute Amiga path with volume prefix is expected. Any other path returns None. If volume does not exist also return None. It replaces the volume with the sys_path prefix. Furthermore, the remaining Amiga path is mapped to the system file system and case corrected if a corresponding entry is found. If 'fast' mode is enabled then the original case of the path elements is kept if the underlying FS is case insensitive. Return None on error or system path """ # find volume pos = ami_path.find(':') if pos <= 0: log_path.debug("vol: ami_to_sys_path: empty volume: %s", ami_path) return None vol_name = ami_path[:pos].lower() # check volume name if vol_name in self.vols_by_name: volume = self.vols_by_name[vol_name] vol_sys_path = volume.get_path() remainder = ami_path[pos + 1:] # only volume name given if len(remainder) == 0: log_path.info("vol: direct volume: ami='%s' -> sys='%s'", ami_path, vol_sys_path) return vol_sys_path # invalid volume:/... path if remainder[0] == '/': log_path.error("vol: ami_to_sys_path: invalid :/ path: %s", ami_path) return None # follow ami path along in sys world dirs = remainder.split('/') sys_path = self._follow_path_no_case(vol_sys_path, dirs, fast) log_path.info("vol: ami_to_sys_path: ami='%s' -> sys='%s'", ami_path, sys_path) return sys_path else: log_path.error("vol: ami_to_sys_path: volume='%s' not found: %s", vol_name, ami_path) return None
def ami_to_sys_path(self, ami_path, fast=False): """Map an Amiga path to a system path. An absolute Amiga path with volume prefix is expected. Any other path returns None. If volume does not exist also return None. It replaces the volume with the sys_path prefix. Furthermore, the remaining Amiga path is mapped to the system file system and case corrected if a corresponding entry is found. If 'fast' mode is enabled then the original case of the path elements is kept if the underlying FS is case insensitive. Return None on error or system path """ # find volume pos = ami_path.find(':') if pos <= 0: log_path.debug("vol: ami_to_sys_path: empty volume: %s", ami_path) return None vol_name = ami_path[:pos].lower() # check volume name if vol_name in self.vols_by_name: volume = self.vols_by_name[vol_name] vol_sys_path = volume.get_path() remainder = ami_path[pos+1:] # only volume name given if len(remainder) == 0: log_path.info("vol: direct volume: ami='%s' -> sys='%s'", ami_path, vol_sys_path) return vol_sys_path # invalid volume:/... path if remainder[0] == '/': log_path.error("vol: ami_to_sys_path: invalid :/ path: %s", ami_path) return None # follow ami path along in sys world dirs = remainder.split('/') sys_path = self._follow_path_no_case(vol_sys_path, dirs, fast) log_path.info("vol: ami_to_sys_path: ami='%s' -> sys='%s'", ami_path, sys_path) return sys_path else: log_path.error("vol: ami_to_sys_path: volume='%s' not found: %s", vol_name, ami_path) return None
def create_env(self, cwd=None, cmd_paths=None): """return a new AmiPathEnv either share cwd or cmd_paths with current default env or set own values. make sure that the env has a valid path_resolver """ if cwd is None: cwd = self.default_env.get_cwd() if cmd_paths is None: cmd_paths = self.default_env.get_cmd_paths() env = PathManagerEnv(self, cwd, cmd_paths) env.resolve() log_path.info("created env: %s", env) return env
def _setup_base_dir(self): # ensure that vols_base_dir exists base_dir = self.vols_base_dir if not base_dir: raise ValueError("volume manager: no base dir given!") base_dir = resolve_sys_path(base_dir) if not os.path.isdir(base_dir): try: log_path.info("creating volume base dir: %s", base_dir) os.makedirs(base_dir) except OSError as e: log_path.error("error creating volume base dir: %s -> %s", base_dir, e) return None else: log_path.debug("found base dir: %s", base_dir) return base_dir
def ami_command_to_sys_path(self, cwd_lock, ami_path): """lookup a command on path if it does not contain a relative or absolute path. otherwise perform normal 'ami_to_sys_path' conversion""" env = self._get_lock_env(cwd_lock) cmd_paths = self.cmdpaths(ami_path, env=env) log_path.info( "ami_command_to_sys_path: ami_path=%s -> cmd_paths=%s", ami_path, ",".join(map(str, cmd_paths)), ) # check if ami path exists as sys path for cmd_path in cmd_paths: sys_path = self.to_sys_path(str(cmd_path)) if os.path.isfile(sys_path): log_path.info( "ami_command_to_sys_path: ami_path=%s -> sys_path=%s, ami_path=%s", ami_path, sys_path, cmd_path, ) return sys_path, cmd_path # nothing found log_path.info("ami_command_to_sys_path: ami_path='%s' not found!", ami_path) return None, None
def add_volume(self, name, sys_path): # ensure volume name is lower case lo_name = name.lower() # check path and name sys_path = self.resolve_sys_path(sys_path) if not os.path.isdir(sys_path): log_path.error("invalid volume path: '%s' -> %s" % (name, sys_path)) return False elif sys_path in self.sys2volume: log_path.error("duplicate volume mapping: '%s' -> %s" % (name, sys_path)) return False elif lo_name in self.volume2sys: log_path.error("duplicate volume name: '%s'", name) return False else: log_path.info("add volume: '%s:' -> %s", name, sys_path) self.volume2sys[lo_name] = sys_path self.sys2volume[sys_path] = lo_name self.orig_names[lo_name] = name return True
def setup(self, mgr): vmgr = mgr.get_volume_mgr() for a in self.assigns: log_path.info("assign '%s': checking: %s", self.name, a) # check assign volpaths = mgr.resolve_assigns(a, as_list=True) for volpath in volpaths: res = mgr._split_volume_remainder(volpath) if res is None: log_path.error("assign '%s': no absolute path: %s", self.name, volpath) return False # resolve volume volname, rel_dir = res volume = vmgr.get_volume(volname) if not volume: log_path.error("assign '%s': volume not found: %s", self.name, a) return False # create assign dir? if 'create' in self.cfg: if not self._create_dir(volume, rel_dir): return False return True
def setup(self, mgr): vmgr = mgr.get_volume_mgr() for a in self.assigns: log_path.info("assign '%s': checking: %s", self.name, a) # check assign volpaths = mgr.resolve_assigns(a, as_list=True) for volpath in volpaths: res = mgr._split_volume_remainder(volpath) if res is None: log_path.error( "assign '%s': no absolute path: %s", self.name, volpath ) return False # resolve volume volname, rel_dir = res volume = vmgr.get_volume(volname) if not volume: log_path.error("assign '%s': volume not found: %s", self.name, a) return False # create assign dir? if "create" in self.cfg: if not self._create_dir(volume, rel_dir): return False return True
def add_assign(self, name, path_list, append=False): # also allow path string instead of list if type(path_list) is str: path_list = [path_list] # check name: empty? if len(name) == 0: log_path.error("empty assign added!") return False # check name: is volume? lo_name = name.lower() if self.vol_mgr.is_volume(lo_name): log_path.error("assign with a volume name: %s", name) return False # check name: duplicate assign elif lo_name in self.assigns: log_path.error("duplicate assign: %s", name) return False # check path_list alist = [] for path_name in path_list: if not self._ensure_volume_or_assign(path_name): return False alist.append(path_name) # setup assign list if append and self.assigns.has_key(lo_name): self.assigns[lo_name] += alist else: self.assigns[lo_name] = alist # save exact cased name self.orig_names[lo_name] = name log_path.info("add assign: name='%s' -> paths=%s", name, alist) return True
def ami_to_sys_path(self, cwd_lock, ami_path, searchMulti=False, mustExist=False): env = self._get_lock_env(cwd_lock) paths = self.volpaths(ami_path, env=env) if len(paths) == 0: log_path.info("ami_to_sys_path: ami_path='%s' -> None") return None # now we have paths with volume:abs/path sys_path = None # search for existing multi assign if searchMulti or mustExist: for npath in paths: # first try to find existing path in all locations spath = self.to_sys_path(str(npath)) if spath and os.path.exists(spath): sys_path = spath break # nothing found -> try first path if sys_path is None and not mustExist: sys_path = self.to_sys_path(str(paths[0])) log_path.info("ami_to_sys_path: ami_path='%s'" " -> volpaths=%s -> sys_path='%s'", ami_path, ",".join(map(str, paths)), sys_path) return sys_path
def resolve_assigns(self, ami_path, recursive=True): """replace all assigns found in path until only a volume path exists. do not touch relative paths or abs paths without assign prefix. return: original path if path is not absolute or does not contain assign prefix or: string if no multi assigns are involved or: list of string if multi assigns were encountered """ log_path.info("resolve_assign: ami_path='%s'", ami_path) split = self._split_volume_remainder(ami_path) if split is None: # relative path log_path.debug("resolve_assign: ami_path='%s' is rel_path!", ami_path) return ami_path else: # is assign name = split[0].lower() if self.assigns.has_key(name): remainder = split[1] aname_list = self.assigns[name] # single assign if len(aname_list) == 1: aname = aname_list[0] new_path = self._concat_assign(aname, remainder) log_path.info( "resolve_assign: ami_path='%s' -> single assign: '%s'", ami_path, new_path) if recursive: return self.resolve_assigns(new_path) else: return new_path # multi assign else: result = [] for aname in aname_list: new_path = self._concat_assign(aname, remainder) log_path.info( "resolve_assign: ami_path='%s' -> multi assign: '%s'", ami_path, new_path) if recursive: new_path = self.resolve_assigns(new_path) if new_path is None: return None if type(new_path) is str: result.append(new_path) else: result += new_path return result # prefix is not an assign else: log_path.debug("resolve_assign: ami_path='%s' has no assign!", ami_path) return ami_path
def ami_command_to_sys_path(self, cwd_lock, ami_path): """lookup a command on path if it does not contain a relative or absolute path. otherwise perform normal 'ami_to_sys_path' conversion""" env = self._get_lock_env(cwd_lock) cmd_paths = self.cmdpaths(ami_path, env=env) log_path.info( "ami_command_to_sys_path: ami_path=%s -> cmd_paths=%s", ami_path, ",".join(map(str, cmd_paths))) # check if ami path exists as sys path for cmd_path in cmd_paths: sys_path = self.to_sys_path(str(cmd_path)) if os.path.isfile(sys_path): log_path.info( "ami_command_to_sys_path: ami_path=%s -> sys_path=%s, ami_path=%s", ami_path, sys_path, cmd_path) return sys_path, cmd_path # nothing found log_path.info( "ami_command_to_sys_path: ami_path='%s' not found!", ami_path) return None, None
def dump(self): log_path.info("--- volume config ---") for volume in self.volumes: log_path.info("%s", volume)
def dump(self): log_path.info("--- env ---") log_path.info("cwd: %s", self.cwd) log_path.info("cmd_paths: %s", self.cmd_paths)
def shutdown(self): log_path.debug("shutting down assigns") for a in self.assigns: log_path.info("cleaning up assign: %s", a) a.shutdown() a.is_setup = False
def sys_to_ami_path(self, sys_path): ami_path = self.from_sys_path(sys_path) log_path.info("sys_to_ami_path: sys_path='%s' -> abs_path='%s' " "-> ami_path='%s'", sys_path, ami_path) return ami_path
def ami_path_exists(self, cwd_lock, ami_path): sys_path = self.ami_to_sys_path(cwd_lock, ami_path, mustExist=True) exists = os.path.exists(str(sys_path)) log_path.info("ami_path_exists: path='%s' -> sys_path='%s' -> exists=%s", ami_path, sys_path, exists) return exists
def resolve_assigns(self, ami_path, recursive=True, as_list=False): """replace all assigns found in path until only a volume path exists. do not touch relative paths or abs paths without assign prefix. return: original path if path is not absolute or does not contain assign prefix or: string if no multi assigns are involved or: list of string if multi assigns were encountered """ log_path.info("resolve_assign: ami_path='%s'", ami_path) split = self._split_volume_remainder(ami_path) if split is None: # relative path log_path.debug("resolve_assign: ami_path='%s' is rel_path!", ami_path) if as_list: return [ami_path] else: return ami_path else: # is assign name = split[0].lower() if self.assigns_by_name.has_key(name): remainder = split[1] assign = self.assigns_by_name[name] aname_list = assign.get_assigns() # single assign if len(aname_list) == 1: aname = aname_list[0] new_path = self._concat_assign(aname, remainder) log_path.info("resolve_assign: ami_path='%s' -> single assign: '%s'", ami_path, new_path) if recursive: return self.resolve_assigns(new_path, recursive, as_list) elif as_list: return [new_path] else: return new_path # multi assign else: result = [] for aname in aname_list: new_path = self._concat_assign(aname, remainder) log_path.info( "resolve_assign: ami_path='%s' -> multi assign: '%s'", ami_path, new_path) if recursive: new_path = self.resolve_assigns(new_path, recursive, as_list) if new_path is None: return None if type(new_path) is str: result.append(new_path) else: result += new_path return result # prefix is not an assign else: log_path.debug("resolve_assign: ami_path='%s' has no assign!", ami_path) if as_list: return [ami_path] else: return ami_path
def dump(self): log_path.info("--- assigns ---") for a in self.assigns: log_path.info("%s", a)
def ami_dir_of_path(self, cwd_lock, path): env = self._get_lock_env(cwd_lock) abs_path = self.abspath(path, env=env) abs_dir = abs_path.absdirname() log_path.info("ami_dir_of_path: path='%s' -> dir='%s'", path, abs_dir) return abs_dir