def callback_target(): try: fh = os.fdopen(prfd) except: os.close(prfd) raise while True: arg_count = fh.readline().strip() if not arg_count: break arg_count = int(arg_count) args = [] for arg_i in range(arg_count): arg_len = int(fh.readline()) args.append(fh.read(arg_len)) name = args[0] if name in callbacks: try: res = callbacks[name](*args[1:]) except Exception as e: log.exception('exception in callback %s: %s' % (name, e)) res = None else: log.warning('no callback %s' % name) res = None if res is None: os.write(pwfd, '0\n') else: res = str(res) os.write(pwfd, '%s\n' % len(res)) os.write(pwfd, res)
def rewrite_shebang(self, old_path, new_path): # Only care if it is at all executable. stat = os.stat(old_path) if not (stat.st_mode & 0o111): return # If it starts with a Python shebang, rewrite it. with open(old_path, 'rb') as old_fh: old_shebang = old_fh.readline() m = re.match(r'#!(|\S+/)([^\s/]+)', old_shebang) if not m: return new_bin = os.path.join(self.path, 'bin', m.group(2)) if not os.path.exists(new_bin): return new_shebang = '#!%s%s' % (new_bin, old_shebang[m.end(2):]) log.info('Rewriting shebang of %s' % old_path, verbosity=1) log.debug('New shebang: %s' % new_shebang.strip(), verbosity=1) self._assert_real_dir(os.path.dirname(new_path)) # Due to the way the _assert_real_dir works, we may have already # created a symlink in the location of the new_path which points to # the old_path. If we don't delete it first, then we will be # reading and writing to the same time, and will only get the # shebang + 1024 bytes (the buffer size on my machine). if os.path.lexists(new_path): os.unlink(new_path) with open(new_path, 'wb') as new_fh: new_fh.write(new_shebang) new_fh.writelines(old_fh) try: shutil.copystat(old_path, new_path) except OSError as e: # These often come up when you are not the owner # of the file. log.exception('Could not copystat to %s' % new_path) if e.errno != errno.EPERM: raise return True
def install(self, names=None, link_env=None, reinstall=False, relink=False, no_deps=False): # I'd love to split this method into an "install" and "link" step, but # then we'd need to reimplement the dependency resolution. That would # be a good idea to do anyways, but... meh. if isinstance(names, str): names = [names] names = list(names if names else self.keys()) for name in names: if name not in self: raise KeyError(name) if not isinstance(reinstall, set): reinstall = set( names if no_deps else self.keys()) if reinstall else set() if not isinstance(relink, set): relink = set( names if no_deps else self.keys()) if relink else set() while names: name = names.pop(0) self._parent_names.setdefault(name, None) parent_chain = [] tip = name while tip and tip not in parent_chain: parent_chain.append(tip) tip = self._parent_names.get(tip) parent_chain = parent_chain[1:] print( '==>', style(name, 'blue'), style('(%s)' % ' < '.join(parent_chain), faint=True) if parent_chain else '') with log.indent(): # Avoid infinite error loops. if name in self._errored: log.warning('Skipping due to previous error.') continue try: self._install_one(names, name, link_env, reinstall, relink, no_deps) except PipelineError as e: self._errored.add(name) log.error(str(e)) continue except Exception as e: self._errored.add(name) print_cli_exc(e, verbose=True) log.exception('Exception while processing %s' % name) continue if self._errored: log.warning('There were errors in: %s' % ', '.join(sorted(self._errored)))
def link(args): """Link the given requirement or requirements into the given environment, e.g.:: # Install and link a single package. $ vee link [email protected]:vfxetc/sgmock # Install and link multiple packages. $ vee link [email protected]:vfxetc/sgmock [email protected]:vfxetc/sgsession \\ http:/example.org/path/to/tarball.tgz --make-install # Install and link from a requirement set. $ vee link path/to/manifest.txt """ if args.no_install and args.re_install: raise ValueError( 'please use only one of --no-install and --re-install') home = args.assert_home() if sum( int(bool(x)) for x in (args.repo, args.environment, args.directory)) > 1: raise ValueError( 'use only one of --repo, --environment, or --directory') if args.environment: env = Environment(args.environment, home=home) elif args.directory: env = Environment(os.path.abspath(args.directory), home=home) else: repo = home.get_repo(args.repo) env = Environment('%s/%s' % (repo.name, repo.branch_name), home=home) if args.raw: for dir_ in args.requirements: log.info(style_note('Linking', dir_)) env.link_directory(dir_) return manifest = Manifest(args.requirements, home=home) pkg_set = PackageSet(env=env, home=home) # Register the whole set, so that dependencies are pulled from here instead # of weakly resolved from installed packages. pkg_set.resolve_set(manifest) for req in manifest.iter_packages(): # Skip if it wasn't requested. if args.subset and req.name not in args.subset: continue log.info(style('==> %s' % req.name, 'blue')) pkg = pkg_set.resolve(req, check_existing=not args.reinstall) if args.no_install and not pkg.installed: raise CliError('not installed: %s' % req) try: with log.indent(): pkg_set.install(pkg.name, link_env=env, reinstall=args.reinstall, relink=args.force) except AlreadyInstalled: pass except AlreadyLinked as e: log.info(style('Already linked ', 'blue') + str(req), verbosity=1) except Exception as e: print_cli_exc(e, verbose=True) log.exception('Failed to link %s' % req) continue