def git(args, *command): if not (args.all or args.name): log.error("Please provide -n NAME or --all.") return 1 if not command: log.error('Please provide a git command.') return 1 home = args.assert_home() retcode = 0 if args.all: dev_pkgs = home.iter_development_packages() else: dev_pkgs = [] for name in args.names: dev_pkg = home.find_development_package(name) if not dev_pkg: log.error("Could not find dev package: {!r}.".format(name)) return 2 dev_pkgs.append(dev_pkg) for dev_pkg in dev_pkgs: log.info(style_note(dev_pkg.name, ' '.join(command))) try: dev_pkg.git(*command, verbosity=0, indent=False) except Exception as e: print_cli_exc(e) retcode = 1 return retcode
def git(args, *command): if not command: print style_error('please provide a git command') return 1 home = args.assert_home() retcode = 0 for dev_pkg in home.iter_development_packages(): log.info(style_note(dev_pkg.name, ' '.join(command))) try: dev_pkg.git(*command, verbosity=0, indent=False) except Exception as e: print_cli_exc(e) retcode = 1 return retcode
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 init(args, do_clone=False, do_install=False, do_add=False, is_find=False): do_init = not (do_clone or do_install or do_add) name = args.name home = args.assert_home() con = home.db.connect() path = os.path.abspath(args.path or os.path.join(home.dev_root, name)) dev_repo = GitRepo(path) if do_init: log.info(style_note('Initing %s' % dev_repo.work_tree)) makedirs(dev_repo.work_tree) dev_repo.git('init') elif do_clone: log.info(style_note('Cloning %s' % args.url)) makedirs(dev_repo.work_tree) dev_repo.clone_if_not_exists(args.url) elif do_install: # Find an existing tool. # TODO: put more of this into EnvironmentRepo or Manifest repo = home.get_repo(args.repo) manifest_path = os.path.join(repo.work_tree, 'manifest.txt') manifest = Manifest(manifest_path, home=home) for req in manifest.iter_packages(): if req.name.lower() == name.lower(): # Make sure it is a Git package. url = normalize_git_url(req.url, prefix=False) if url: break else: log.error('Could not find git-based "%s" in "%s" repo.' % (name, repo.name)) return 2 log.info(style_note('Found %s in %s' % (name, repo.name), str(req))) makedirs(dev_repo.work_tree) dev_repo.clone_if_not_exists(url, shallow=False) elif do_add: log.info(style_note('Adding %s from %s' % (name, path))) if not os.path.exists(path): log.error('%s does not exist' % path) return 1 package = Package([path], home=home, dev=True) try: package.pipeline.run_to('develop') except Exception as e: print_cli_exc(e) return 1 log.info(style_note('Linking dev package', name, path)) dev_pkg = DevPackage( { 'name': name, 'path': path, 'environ': package.environ }, home=home) dev_pkg.save_tag()
def main(argv=None, environ=None, as_main=__name__ == "__main__"): try: if argv is None: argv = sys.argv[1:] # Split up args in shebangs if we seem to be in a situation where # it wasn't done for us. raw_argv = argv argv = [] for arg in raw_argv: if '--shebang ' in arg: argv.extend(arg.split()) else: argv.append(arg) argv = [x for x in argv if x != '--shebang'] parser = get_parser() args, unparsed = parser.parse_known_args(argv, namespace=Namespace()) func = get_func(args) if func and unparsed and not func.__parse_known_args: args = parser.parse_args(argv, namespace=Namespace()) func = get_func(args) args.environ = os.environ if environ is None else environ args.home_path = default_home_path(environ=args.environ) if args.real_prefix and args.real_prefix != getattr( sys, 'real_prefix', None): sys.real_prefix = args.real_prefix if args.log: root = logging.getLogger('vee') stream = sys.stdout if args.log == '-' else open(args.log, 'ab') handler = logging.StreamHandler(stream) handler.setFormatter( _LogFormatter( '%(asctime)-15s %(name)s %(levelname)s: %(message)s')) root.addHandler(handler) # When called recursively, we want to maintain at least the previous # level of verbosity. log.config.verbosity = max(log.config.verbosity, args.verbose or 0) # TODO: Move this to a $VEE_UMASK envvar or something. # For now, just leave all permissions open. os.umask(0) if func: lock = None try: # Don't grab the lock if we dont need it (or if the home isn't set) if func.__acquire_lock and args.home_path and os.path.exists( args.home_path): try: lock = _global_locks[args.home_path] except KeyError: lock_content = ( os.environ.get('VEE_LOCK_CONTENT') or '%s@%s/%s' % ( os.environ.get('LOGNAME', '<unknown>'), os.environ.get('SSH_CLIENT', 'localhost').split()[0], os.getpid(), )) lock = RLockfile(os.path.join(args.home_path, '.vee-lock'), blocking=False, content=lock_content) _global_locks[args.home_path] = lock lock.acquire() except IOError as e: if e.errno == errno.EWOULDBLOCK: content = lock.get_content() log.error('VEE is locked%s' % (': ' + content if content else '', )) res = 1 else: raise else: if args.cprofile_path: res = cProfile.runctx('func(args, *unparsed)', locals(), globals(), filename=args.cprofile_path) or 0 else: res = func(args, *unparsed) or 0 if func.__acquire_lock and lock is not None: lock.release() else: parser.print_help() res = 1 except Exception as e: if as_main: print_cli_exc(e, verbose=True) res = cli_errno(e) else: raise return res
def init(args, do_clone=False, do_install=False, do_add=False, is_find=False): do_init = not (do_clone or do_install or do_add) name = args.name home = args.assert_home() con = home.db.connect() # Make sure there are no other packages already, and clear out old ones # which no longer exist. for row in con.execute('SELECT * FROM development_packages WHERE name = ?', [name]): if not args.force and os.path.exists(os.path.join(row['path'], '.git')): if is_find: print style_note('"%s" already exists:' % name, row['path']) return else: print style_error('"%s" already exists:' % name, row['path']) return 1 else: con.execute('DELETE FROM development_packages WHERE id = ?', [row['id']]) path = os.path.abspath(args.path or os.path.join(home.dev_root, name)) dev_repo = GitRepo(path) if do_init: print style_note('Initing %s' % dev_repo.work_tree) makedirs(dev_repo.work_tree) dev_repo.git('init') elif do_clone: print style_note('Cloning %s' % args.url) makedirs(dev_repo.work_tree) dev_repo.clone_if_not_exists(args.url) elif do_install: # Find an existing tool. # TODO: put more of this into EnvironmentRepo or Requirements env_repo = home.get_env_repo(args.repo) req_path = os.path.join(env_repo.work_tree, 'requirements.txt') reqs = Requirements(req_path, home=home) for req in reqs.iter_packages(): if req.name.lower() == name.lower(): # Make sure it is a Git package. url = normalize_git_url(req.url, prefix=False) if url: break else: print style_error('Could not find git-based "%s" in "%s" repo.' % (name, env_repo.name)) return 2 print style_note('Found %s in %s' % (name, env_repo.name), str(req)) makedirs(dev_repo.work_tree) dev_repo.clone_if_not_exists(url, shallow=False) elif do_add: print style_note('Adding %s from %s' % (name, path)) if not os.path.exists(path): log.error('%s does not exist' % path) return 1 package = Package([path], home=home, dev=True) try: package.pipeline.run_to('develop') except Exception as e: print_cli_exc(e) return 1 print style_note('Linking dev package', name, path) con.execute( 'INSERT INTO development_packages (name, path, environ) VALUES (?, ?, ?)', [name, path, json.dumps(package.environ)]) dev_pkg = DevPackage( { 'name': name, 'path': path, 'environ': package.environ }, home=home) dev_pkg.save_tag()
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